14. 时间效率(5)

题一:【数组中出现次数超过一半的数字】

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

法一:暴力破解——使用Map记录数组中每个数字出现的次数

 1 import java.util.*;
 2 public class Solution {
 3     public int MoreThanHalfNum_Solution(int [] array) {
 4         HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
 5         int len = array.length;
 6         for(int i=0;i<len;i++){
 7             if(map.containsKey(array[i])){
 8                 map.replace(array[i],map.get(array[i])+1);
 9                 if(map.get(array[i])>=(len+2)/2){
10                     return array[i];
11                 }
12             }else{
13                 map.put(array[i],1);
14                 if(map.get(array[i])>=(len+2)/2){
15                     return array[i];
16                 }
17             }
18         }
19         return 0;
20     }
21 }

法二:也可以先将数组排序,再遍历查看是否有连续的(长度大于数组长度一半)元素。

 

题二:【最小的K个数】

 输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

分析:先排序,再取数组元素

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
 4         ArrayList<Integer> list = new ArrayList<Integer>();
 5         if(input==null||input.length==0||k<=0||k>input.length) return list;
 6         quickSort(input,0,input.length-1);
 7         for(int i=0;i<k;i++){
 8             list.add(input[i]);
 9         }
10         return list;
11     }
12     public void quickSort(int[] input,int left, int right){
13         int base = input[left];
14         int leftNum = left;
15         int rightNum = right;
16         while(left<right){
17             while(left<right&&input[right]>=base){
18                 right--;
19             }
20             while(left<right&&input[left]<=base){
21                 left++;
22             }
23             swap(input,left,right);
24         }
25         swap(input,leftNum,left);
26         quickSort(input,leftNum,left-1);
27         quickSort(input,right+1,rightNum);
28     }
29     public void swap(int[] input, int i, int j){
30         int tmp = input[i];
31         input[i] = input[j];
32         input[j] = tmp;
33     }
34 }

 

分析二:快排拓展,数组取最小k个元素,即0~k-1索引处的元素比k~input.length-1的值都小。可以每次将base索引和k-1比较。

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
 4         ArrayList<Integer> list = new ArrayList<Integer>();
 5         if(input==null||input.length==0||k<=0||k>input.length) return list;
 6         int start = 0;
 7         int end = input.length-1;
 8         int index = quick(input,start,end);
 9         while(index!=k-1){
10             if(index<k-1){
11                 start = index+1;
12             }else{
13                 end = index-1;
14             }
15             index = quick(input,start,end);
16         }
17         for(int i=0;i<k;i++){
18             list.add(input[i]);
19         }
20         return list;
21     }
22     public int quick(int[] input, int start, int end){
23         int base = input[start];
24         int startNum = start;
25         while(start<end){
26             while(start<end&&input[end]>=base){
27                 end--;
28             }
29             while(start<end&&input[start]<=base){
30                 start++;
31             }
32             swap(input,start,end);
33         }
34         swap(input,start,startNum);
35         return start;
36     }
37      public void swap(int[] input, int i, int j){
38          int tmp = input[i];
39          input[i] = input[j];
40          input[j] = tmp;
41      }
42 }

 

题三:【连续子数组的最大和】

 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

分析:求数组中最大连续子数组的和;动态规划;

数组:[6 -3 -2 7 -15 1 2 2]

dp[i]:array[i]和之前所有元素的和最大值;

dp[i] = max{ array[i]+dp[i-1] , array[i] };//如果之前和当前值加在一起还没有当前值大,那么之前的那些都没有价值,还不如直接再从array[i]处开始计算。

sum:整个数组最大子数组的和,也就是dp[i]的最大值;

sum = max{ sum, dp[i] };

 

 1 import java.lang.Math;
 2 public class Solution {
 3     public int FindGreatestSumOfSubArray(int[] array) {
 4         int dp = array[0];//array[i]和之前所有元素的和最大值; 
 5         int sum = array[0];//整个数组最大子数组的和,也就是dp[i]的最大值
 6         for(int i=1;i<array.length;i++){
 7             dp = Math.max(array[i],array[i]+dp);
 8             sum = Math.max(sum, dp);
 9         }
10         return sum;
11     }
12 }

 

 

题四:【整数中1出现的次数】

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

 分析:取余判定,暴力,时间复杂度O(n*k),k是位数。

 1 public class Solution {
 2     public int NumberOf1Between1AndN_Solution(int n) {
 3         if(n<=0) return 0;
 4         if(n==1) return 1;
 5         int count = 1;
 6         for(int i=2;i<=n;i++){
 7             int tmp = i;
 8             while(tmp!=0){
 9                 int remainder = tmp%10;
10                 tmp=tmp/10;
11                 if(remainder==1) count++;
12             }
13         }
14         return count;
15     }
16 }

 

 

题五:【把数组排成最小的数】

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

分析1:先比较每个数的最左位置的数,最小的放在最高位,例如 123  45 6 234,其中123最左边的1是该次比较的最小值,因此把123放在最高位。如果最左位相等,就比较左二位置,直到最后。

分析2:题目中返回值是String,则可以使用String将两个数字拼接。可以自定义一个函数比较字符串大小,比较两个字符串s1, s2大小的时候,先将它们拼接起来,比较s1+s2,和s2+s1那个大,如果s1+s2大,那说明s2应该放前面,所以按这个规则,s2就应该排在s1前面。遍历数组比较一遍之后可以得到排好序的字符串数组,最后可以将拼接整个字符串数组。

 

 1 import java.util.ArrayList;
 2 
 3 public class Solution {
 4     public String PrintMinNumber(int [] numbers) {
 5         String res = "";
 6         for(int i=0;i<numbers.length;i++){
 7             for(int j=i+1;j<numbers.length;j++){
 8                 int a = Integer.valueOf(numbers[i]+""+numbers[j]);
 9                 int b = Integer.valueOf(numbers[j]+""+numbers[i]);
10                 if(a>b){
11                     int tmp = numbers[i];
12                     numbers[i] = numbers[j];
13                     numbers[j] = tmp;
14                 }
15             }
16         }
17         for(int i=0;i<numbers.length;i++){
18             res = res+numbers[i];
19         }
20         return res;
21     }
22 }

 

 

 

 

posted @ 2019-12-17 11:26  Qmillet  阅读(167)  评论(0编辑  收藏  举报