1、A+B問題 給出兩個整數a和b, 求他們的和, 但不能使用 +
等數學運算符
思路:作異或得到未進位和,作與並向左移1位得到進位,隨后再重復操作倆結果,直到進位為0,適合用遞歸

public int aplusb(int a, int b) { int sum = a ^ b; int ca = (a & b) << 1; if (ca == 0) { return sum; } return aplusb(sum, ca); }
2016-12-07
2、尾部的零 設計一個算法,計算出n階乘中尾部零的個數
思路:有多少個5因子尾部就有多少個0,除以一次5獲得包含5的一次方的個數,除以兩次5獲得包含5的兩次方的個數(兩次方有兩個5因子)...以此直到除以5為0跳出

public long trailingZeros(long n) { long num = 0; while (n != 0){ num += n / 5; n /= 5; } return num; }
2016-12-07
3、統計數字 計算數字k在0到n中的出現的次數,k可能是0~9的一個值
tips:由於k是0~9的值,循環時可在k開始,因為小於k的數不可能含有k
思路1:(強行獲得)把所有0到n的數轉成字符串,toCharArray()后用字符數組的每一位與k比較(先把每一位字符通過Character.getNumericValue()變回個位整數)

public int digitCounts(int k, int n) { int num = 0; for (int i = k; i <= n; i++){ //整數變成字符串 String s = String.valueOf(i); //字符串變成字符數組 char[] ss = s.toCharArray(); for (int j = 0; j < s.length(); j++){ //字符變成整數 int a = Character.getNumericValue(ss[j]); if (a == k){ num++; } } } return num; }
思路2:(數學方法獲得)通過與10的余數得到末位,通過與10除去掉末位,構成一個循環,就可以分析一個數的所有位。然后把所有位都加起來(從局部到整體)

public int digitCounts(int k, int n) { int cnt = 0; for (int i = k; i <= n; i++) { //分次計算每一個數中含有k的個數 cnt += singleCount(i, k); } return cnt; } public int singleCount(int i, int k) { //排除0的情況 if (i == 0 && k == 0) return 1; int cnt = 0; while (i > 0) { //判斷末尾是否為k if (i % 10 == k) { cnt++; } //去掉末尾再次循環,直到去除完所有位跳出循環 i = i / 10; } return cnt; }
2016-12-08
4、丑數II 設計一個算法,找出只含素因子2,3,5的第n大的數
思路1:(時間復雜度為O(n))ArrayList動態數組保存每個滿足條件的數,用三個指針遍歷之前的數,分別與2,3,5相乘,得到相乘后能夠比數組中的上一個數大的位置,最后把這三個指針所得結果的最小值加入數組中

public int nthUglyNumber(int n){ List<Integer> uglys = new ArrayList<Integer>(); //創建整形動態數組; uglys.add(1); //把特殊值1首先加入; //分別代表了與2、3、5相乘元素的序號,相當於指針; int p2 = 0, p3 = 0, p5 = 0; //用前面各個位置的數與2,3,5相乘直到比上一個數大,並獲得相應位置; for (int i = 0; i <= n - 2; i++){ //獲取數組中上一個元素,第n個數的上一個對應下標為n-2; int lastNumber = uglys.get(i); while (uglys.get(p2) * 2 <= lastNumber) p2++; while (uglys.get(p3) * 3 <= lastNumber) p3++; while (uglys.get(p5) * 5 <= lastNumber) p5++; //對比p2,p3,p5位置上分別與2,3,5相乘的結果,最小值添加為下一元素; uglys.add(Math.min(Math.min(uglys.get(p2) * 2, uglys.get(p3) * 3), uglys.get(p5) * 5)); } return uglys.get(n - 1); }
思路2:(時間復雜度為O(nlogn))Map來做,還沒看懂答案
2016-12-08
5、在數組中找出第k大元素
思路:利用快排思想,切分位置和k對應就是第k大(由於快排是從小到大,所以對k進行轉換)
warm:好好理解切分思想和遞歸思想

public int kthLargestElement(int k, int[] nums) { if (nums == null || nums.length == 0) { return -1; } if (k <= 0) { return 0; } //使用快速排序,兩指針為頭尾,從小到大排序,需要轉換第幾大 return helper(nums, 0, nums.length - 1, nums.length - k + 1); } public int helper(int[] nums, int l, int r, int k) { if (l == r) { return nums[l]; } //循環切分,直到找到第k大的數,不滿足就遞歸 int position = partition(nums, l, r); if (position == k - 1) { return nums[position]; } else if (position < k - 1) { return helper(nums, position + 1, r, k); } else { return helper(nums, l, position - 1, k); } } public int partition(int[] nums, int l, int r) { //初始化左右指針,定義切分元素 int left = l; int right = r; int pivot = nums[left]; //進行切分,右邊元素小於pivot時賦給左邊,否則移動 while (left < right) { while (left < right && nums[right] >= pivot) { right--; } //第一次循環時切分元素原位置上的數被取代 nums[left] = nums[right]; while (left < right && nums[left] <= pivot) { left++; } nums[right] = nums[left]; } nums[left] = pivot; return left; }
2016-12-15
6、合並兩個排序的整數數組A和B變成一個新的數組
思路:先把兩個數組都不溢出的情況考慮完,再判斷哪一個溢出,一個溢出則另一個肯定不溢出

public int[] mergeSortedArray(int[] A, int[] B) { int m = A.length; int n = B.length; int[] C = new int[m + n]; int i = 0, j = 0, k = 0; while (i < m && j < n) { if (A[i] < B[j]) { C[k++] = A[i++]; } else { C[k++] = B[j++]; } } while (i < m) { C[k++] = A[i++]; } while (j < n) { C[k++] = B[j++]; } return C; }
2016-12-15