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

原文地址:https://www.cnblogs.com/kinghey-java-ljx/p/6142506.html