zoukankan      html  css  js  c++  java
  • 剑指Offer学习笔记(4)——时间效率

    数组中出现次数超过一半的数字
    题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

    public class Solution {
        /**
         * 采用阵地攻守的思想: 第一个数字作为第一个士兵,守阵地;count = 1;
         * 遇到相同元素,count++; 遇到不相同元素,即为敌人,同归于尽,count--;
         * 当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,
         * 有可能是主元素。 再加一次循环,记录这个士兵的个数看是否大于数组一般即可。
         * @param array
         * @return
         */
        public int MoreThanHalfNum_Solution(int[] array) {
            int length = array.length;
            if (array == null || length <= 0) {
                return 0;
            }
     
            int result = array[0];
            int times = 1;
            for (int i = 1; i < length; i++) {
                if (times == 0) {
                    result = array[i];
                    times = 1;
                else {
                    if (array[i] == result) {
                        times++;
                    else {
                        times--;
                    }
                }
            }
     
             
            times = 0;
            for (int i = 0; i < length; i++) {
                if (result == array[i]) {
                    times++;
                }
            }
     
            if (times * 2 < length) {
                result = 0;
            }
            return result;
        }
    }

    最小的K个数
    题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
    import java.util.ArrayList;
    public class Solution {
        /**
         * 最小的K个数
         * @param input
         * @param k
         * @return
         */
        public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
            ArrayList<Integer> aList = new ArrayList<Integer>();
            if (input.length < k || input == null) {
                return aList;
            }
            if (k == 0) {
                return aList;
            }
            int len = input.length;
            findSort(input, 0, len - 1, k);
            for(int i=0;i<k;i++){
                aList.add(input[i]);
            }
            return aList;
        }
     
        /*
        递归查找
        */
        private void findSort(int[] input, int p, int r, int k) {
            if (p == r) {
                return;
            }
            int q = partition(input, p, r);
            int temp = q - p + 1;///当前的长度
             
            if (temp == k) {
                return;
            } else if (k < temp) {
                findSort(input, p, q - 1, k);
            } else {
                findSort(input, q + 1, r, k - temp);
            }
     
        }
       /*
        分治法来实现最小k的查找/*
        */
        private int partition(int[] input, int p, int q) {
            int x = input[q];
            int i = p - 1;
            for (int j = p; j < q ; j++) {
                if (input[j] <= x) {
                    i = i + 1;
                    int temp = input[i];
                    input[i] = input[j];
                    input[j] = temp;
                }
            }
     
            input[q] = input[i + 1];
            input[i + 1] = x;
            return i + 1;
        }
    }
    连续子数组的最大和
    题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    public class Solution {
        /*
        分治法求解最大字数组 这个算法自己曾经实现过 不过有些问题没有解决
         
        */
         
       public int FindGreatestSumOfSubArray(int[] array) {
            if (array.length == 0 || array == null) {
                return 0;
            }
             
            int result = findMaxSubArray(array, 0, array.length - 1);
            return result;
        }
     
        private int findMaxSubArray(int[] arr, int left, int right) {
            int result=0;
            if (left == right) {
                result=arr[left];
                return result;
            else {
                int mid = (left + right) / 2;
                int saleft = findMaxSubArray(arr, left, mid);
                int saright = findMaxSubArray(arr, mid+1, right);
     
                int sacross = findCrossingMaxSubArray(arr, left, mid,
                        right);
     
                if (saleft > saright
                        && saleft > sacross) {
                    return saleft;
                else if (saright > saleft
                        && saright > sacross) {
                    return saright;
                else {
                    return sacross;
                }
            }
        }
     
        private int findCrossingMaxSubArray(int[] arr, int left, int mid, int right) {
            int sum=0;
            int begin=0;
            int end=0;
     
            int leftsum = arr[mid] ;
            sum=arr[mid];
            for(int i=mid-1;i>=left;i--){
                sum=sum+arr[i];
                if(sum>leftsum){
                    leftsum=sum;
                    begin=i;
                }
            }
            int rightsum = arr[mid+1];
            sum=arr[mid+1];
            for(int i=mid+2;i<=right;i++){
                sum=sum+arr[i];
                if(sum>rightsum){
                    rightsum=sum;
                    end=i;
                }
            }
            return leftsum+rightsum;
        }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Solution {
        public static int FindGreatestSumOfSubArray(int[] array) {
            if(array.length==0return 0;
            int sum = 0 ,result = array[0];
            for (int i = 0; i < array.length; i++) {
                if(sum<0)
                    sum = array[i];
                else
                    sum += array[i];
                result = Math.max(result, sum);
            }
            return result;
        }
    }
    整数中1出现的次数(从1到n整数中1出现的次数)
    题目描述:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    public class Solution {
        public int NumberOf1Between1AndN_Solution(int n) {
     
            if(n<=0){
                return 0;
            }
            String str = Integer.toString(n);
            char[] strN=str.toCharArray();
             
            return NumberOf1(strN,0);
             
     
        }
     
        private int NumberOf1(char[] strN,int loc) {
            if(strN==null||strN[loc]<'0'||strN[loc]>'9'||strN[loc]==''){
                return 0;
            }
             
            int first=strN[loc]-'0';
            //剩余长度
            int len = strN.length-loc;//剩余 长度 下标是从0开始
             
            if(len==1&&first==0){
                return 0;
            }
            if(len==1&&first>0){
                return 1;
            }
             
            int numFirstDigit=0;
            if(first>1){
                numFirstDigit=PowerBase10(len-1);
            }else if(first==1){
                numFirstDigit=Atoi(strN,loc+1)+1;//将后序的字符转换成为数值
            }
            //除了开头第一位的所有其他的四位数中的情况
            int numOtherDigit=first*(len-1)*PowerBase10(len-2);
             
            int numRecursive = NumberOf1(strN, loc+1);
             
            return numFirstDigit+numOtherDigit+numRecursive;
             
        }
     
        private int Atoi(char[] strN, int loc) {
            int num = 0;
            for(int i=loc;i<strN.length;i++){
                num=num*10+(strN[i]-'0');
            }
            return num;
        }
     
        private int PowerBase10(int n) {
             
            int res=1;
            for(int i=0;i<n;i++){
                res*=10;
            }
            return res;
        }
    }
    把数组排成最小的数
    题目描述:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    import java.util.ArrayList;
     
    public class Solution {
       /**
         * 生成最小数值的数组排列 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
         * 例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
         *
         * @param numbers
         * @return
         *
         *         这个题目主要是想找到一个排序规则,数组根据这个排序规则来排成一个最小的数字。要确定排序规则就要比较两个数字,也就是比较
         *         m和n,我们需要一个规则判断m和n哪一个应该排在前面,而不是仅仅比较两个数字的值哪个更大。
         *
         *         根据题目要求,两个数字m和n 拼接成为mn和nm如果mn小于nm,那么我们应该打印出mn,也就是m应该排在n 的前面。
         *         我们定义此时m<n.这是我们自定义的大小比较关系。
         *
         *         拼接称为字符串,按照字符串比较大小就可以了。
         */
        public String PrintMinNumber(int[] numbers) {
     
            if (numbers.length == 0 || numbers == null) {
                return "";
            }
     
            int len = numbers.length;
            String[] strNums = new String[len];
            for (int i = 0; i < len; i++) {
                strNums[i] = Integer.toString(numbers[i]);
                // construct string from a int array
            }
     
            String res = qSortStrArray(strNums, len);
     
            return res;
        }
     
        private String qSortStrArray(String[] strNums, int len) {
            if (strNums == null || strNums.length == 0)
                return null;
             
            for(int i=0;i<len-1;i++){
                for(int j=i;j<len;j++){
                    if((strNums[i]+strNums[j]).compareTo(strNums[j]+strNums[i])>0){
                        String temp = strNums[i];
                        strNums[i]=strNums[j];
                        strNums[j]=temp;
                    }
                }
            }
             
            String res="";
            for(int i=0;i<len;i++){
                res+=strNums[i];
            }
            return res;
     
        }
    }
    踏实 踏踏实实~
  • 相关阅读:
    WPF中的brushes
    com中的线程模式(转)
    线程同步
    WPF线程
    应用程序管理(Application)
    WPF的继承结构树
    HTML技巧100例(一)
    多个网站共用一个空间的超值玩法
    用JavaScript实现浏览器地震效果
    HTML技巧100例(二)
  • 原文地址:https://www.cnblogs.com/mrzhang123/p/5365798.html
Copyright © 2011-2022 走看看