取出一個數字 x 的第一個數字,可以將 x 除以 10 直到 x 小於 10 為止,最後的 x 即為第一個數字。
取出一個數字 x 的最後一個數字,可以將 xmod10 即可。
方法一:暴力法(Brute Force)
由於 n≤100,因此可以使用暴力法來解決這個問題。使用兩個迴圈來列舉所有可能的索引組合 (i,j),然後檢查是否這對索引構成一個美麗對。具體來說,我們對 nums[i] 的第一位數字 y 和 nums[j] 的最後一位數字 x 做最大公因數的檢查,若等於 1 則代表兩個數字互質,算作一個美麗對,將答案 ans 加 1。
複雜度分析
時間複雜度:O(n2logM) ,其中 n 是陣列 nums 的長度, M 是陣列 nums 中的最大值。
遍歷所有可能的 (i,j) 對需要 O(n2) 的時間。
計算 nums[i] 的第一位數字 y 需要 O(logM) 的時間。
由於 x,y<10 ,因此計算最大公因數的時間可以視為常數時間。
空間複雜度:O(1) 。
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defcountBeautifulPairs(self, nums: List[int]) -> int: n = len(nums) ans = 0 for i inrange(n): for j inrange(i+1, n): y = nums[i] while y >= 10: y //= 10 x = nums[j] % 10 if gcd(y, x) == 1: ans += 1 return ans
classSolution { public: intcountBeautifulPairs(vector<int>& nums){ int n = nums.size(), ans = 0; for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { int y = nums[i]; while (y >= 10) { y /= 10; } int x = nums[j] % 10; if (gcd(y, x) == 1) { // or __gcd ans++; } } } return ans; } intgcd(int a, int b){ return b ? gcd(b, a % b) : a; } };
方法二:計數(Counting)
從方法一中可以發現,對於 nums[j] 的最後一位數字 x ,只需要考慮前面有多少數字的第一個數字 y 與 x 互質即可。
classSolution: defcountBeautifulPairs(self, nums: List[int]) -> int: ans = 0 cnt = [0] * 10 for x in nums: for y inrange(1, 10): if gcd(y, x % 10) == 1: ans += cnt[y] while x >= 10: x //= 10 cnt[x] += 1 return ans
classSolution { public: intcountBeautifulPairs(vector<int>& nums){ int n = nums.size(), ans = 0; vector<int> cnt(10); for (int x : nums) { for (int y = 1; y < 10; y++) { if (gcd(y, x % 10) == 1) { // or __gcd ans += cnt[y]; } } while (x >= 10) { x /= 10; } cnt[x]++; } return ans; } intgcd(int a, int b){ return b ? gcd(b, a % b) : a; } };
寫在最後
Cover photo is generated by @たろたろ, thanks for their work!