• 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 }

     

  • 相关阅读:
    Search Insert Position——二分法
    Majority Element——算法课上的一道题(经典)
    Max Points on a Line——数学&&Map
    Valid Number——分情况讨论最经典的题(没细看)——这题必须静下心来好好看看
    Sqrt(x)——二分法,防越界
    Ubuntu系统---NVIDIA 驱动安装
    系统---《windows + ubuntu双系统》
    VS---《在VS2010中 使用C++创建和使用DLL》(003)
    VS---《在VS2010中 使用C++创建和使用DLL》(002)
    图像处理---《在图片上打印文字 windows+GDI+TrueType字体》
  • 原文地址:https://www.cnblogs.com/qmillet/p/12048069.html
Copyright © 2020-2023  润新知