• 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

  • 相关阅读:
    mysql使用group by查询报错SELECT list is not in GROUP BY clause and contains nonaggregated column...解决方案
    CentOS7 使用minikube 搭建kubernetes 学习环境
    5
    4
    3
    2
    1
    8
    7
    Algorithm
  • 原文地址:https://www.cnblogs.com/kinghey-java-ljx/p/6142506.html
Copyright © 2020-2023  润新知