Lintcode答案&筆記


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);
    }
View Code

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;
    }
View Code

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;
    }
View Code

思路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;
    }
View Code

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);
    }
View Code

思路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;
    }
View Code

 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;
    }
View Code

2016-12-15

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM