大水题集合

1.顺时针打印矩阵:

思路:先打印第一行,旋转数组。再打印第一行,一直到数组没有内容了。

public ArrayList<Integer> printMatrix(int [][] matrix) {
       ArrayList<Integer> list=new ArrayList<Integer>();
       int row=matrix.length;
        while(row!=0){
            for(int i=0;i<matrix[0].length;i++){
                list.add(matrix[0][i]);
            }
            if(row==1) break;
            matrix=turnOver(matrix);
            row=matrix.length;
        }
        return list;
    }
    private int[][] turnOver(int[][] matrix){
        int col=matrix[0].length;
        int row=matrix.length;
        int[][] newMatrix=new int[col][row-1];
        for(int i=col-1;i>=0;i--){
            for(int j=1;j<row;j++){
                newMatrix[col-1-i][j-1]=matrix[j][i];
            }
        }
        return newMatrix;
    } 

 2.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323

非常巧妙的方法:

public String PrintMinNumber(int[] numbers) {
      String s="";
      ArrayList<Integer> list= new ArrayList<Integer>();
      for(int i=0;i<numbers.length;i++){
          list.add(numbers[i]);
      }
      Collections.sort(list, new Comparator<Integer>(){      
          public int compare(Integer str1,Integer str2){
                 String s1=str1+""+str2;
                 String s2=str2+""+str1;
                 return s1.compareTo(s2);
          }
      });      
      for(int j:list){
         s+=j;
      }
      return s;
}

3.只含有2,3,5的数称为丑数,按从小到大的第N个丑数,1是第一个丑数。

public int GetUglyNumber_Solution(int index) {
        if(index<7) return index;
        int[] ret = new int[index];
        ret[0]=1;
        int t2=0,t3=0,t5=0;
        for(int i=1;i<index;i++) {
            ret[i] = Math.min(Math.min(ret[t2]*2,ret[t3]*3),ret[t5]*5);
            if(ret[i] == ret[t2]*2) t2++;
            if(ret[i] == ret[t3]*3) t3++;
            if(ret[i] == ret[t5]*5) t5++;
        }
        return ret[index-1];
}

4.第一次只出现一次的字符,注意数据结构的选择。

public int FirstNotRepeatingChar(String str) {
        LinkedHashMap<Character , Integer> map = new LinkedHashMap<Character, Integer>();
        for(int i=0;i<str.length();i++){
            if(map.containsKey(str.charAt(i))){
                int time = map.get(str.charAt(i));
                map.put(str.charAt(i), ++time);
            }
            else {
                map.put(str.charAt(i), 1);
            }
        }
        int pos = -1;  
        for(int i=0;i<str.length();i++){
            char c = str.charAt(i);
            if (map.get(c) == 1) {
                return i;
            }
        }
        return pos;
}

 5.统计一个数字在排序数组中出现的次数

二分查找,找这个数字+0.5插入的位置减去这个数字-0.5的位置

6.一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

异或运算加上位图法

8.沿着对角线打印矩阵:先打印右上方,每次行列都加1,再打印左下方,也是每次行列都加1

时间复杂度O(n^2)

private void print(int a[][], int n) {
        int row;
        int col;
        //输出右上角代码,包括对角线上的元素
        for (int i = n - 1; i >= 0; i--) {//每次都是从第0行开始,所以需要row = 0,然后row  col  同时自增
            row = 0;
            col = i;
            while (row >= 0 && row < n && col >= 0 && col < n) {
                System.out.println(a[row][col]);
                row++;
                col++;
            }
        } 
        //for输出左下角代码,对角线上的元素已经打印完了,所以在这里从1开始
        for (int i = 1; i <= n - 1; i++) {//每次都是从第0列开始,所以需要col = 0,然后row  col  同时自增
            row = i;
            col = 0;
            while (row >= 0 && row < n && col >= 0 && col < n) {
                System.out.println(a[row][col]);
                row++;
                col++;
            }
        }
    }

 9.一个从上到下,从左到右递增的二维数组,找出目标值,

思路:从左下或者右上开始找

public boolean Find(int [][] array,int target) {
        int row=0;
        int col=array[0].length-1;
        while(row<=array.length-1&&col>=0){
            if(target==array[row][col])
                return true;
            else if(target>array[row][col])
                row++;
            else
                col--;
        }
        return false;
}

和上面类似,在从左到右从上到小都排好序的二维数组中找出第k大的值,

二分法 

public int kthSmallest(int[][] matrix, int k) {
    int m = matrix.length, n = matrix[0].length;
    int lo = matrix[0][0], hi = matrix[m - 1][n - 1];
    while(lo <= hi) {
        int mid = lo + (hi - lo) / 2;
        int cnt = 0;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n && matrix[i][j] <= mid; j++) {
                cnt++;
            }
        }
        if(cnt < k) lo = mid + 1;
        else hi = mid - 1;
    }
    return lo;
}

时间复杂度n*n*logn,先用二分找到那个数,再去遍历

小根堆,每次弹出最小的,弹k-1次,那么剩下的就是第k个

public int kthSmallest(int[][] matrix, int k) {
        int m = matrix.length, n = matrix[0].length;
        PriorityQueue<Tuple> pq = new PriorityQueue<Tuple>();
        for(int j = 0; j < n; j++) pq.offer(new Tuple(0, j, matrix[0][j]));
        for(int i = 0; i < k - 1; i++) { // 小根堆,去掉 k - 1 个堆顶元素,此时堆顶元素就是第 k 的数
            Tuple t = pq.poll();
            if(t.x == m - 1) continue;//到达最下面的行了
            pq.offer(new Tuple(t.x + 1, t.y, matrix[t.x + 1][t.y]));
        }
        return pq.poll().val;
    }
static class Tuple implements Comparable<Tuple> {
        int x, y, val;
        public Tuple(int x, int y, int val) {
            this.x = x; this.y = y; this.val = val;
        }
        @Override
        public int compareTo(Tuple that) {
            return this.val - that.val;
        }    
    }

10.使一个数组奇数插在前面,偶数插在后面,但相对顺序不变

思路:就是简单插入排序的应用

public void reOrderArray(int [] array) {
        int n=array.length;
        for(int i=1;i<n;i++) {
            int temp=array[i];
            int j=i-1;
            if(Solution.isEven(temp)) {
                array[j+1]=temp;//偶数直接插到最后
            }
            else
            {
                //是奇数
                while(j>=0&&Solution.isEven(array[j])) {
                   array[j+1]=array[j];
                   j--;
                }
                array[j+1]=temp;
            }
            
        }
    }
    static boolean isEven(int n){
        if(n%2==0)
            return true;
        return false;
    }

 11.求两个排序数组的中位数

public static double findMidByCounter(int[] a, int[] b) {  
        int ai = 0, bi = 0;  
        int lena=a.length,lenb=b.length;
        int k=(lena+lenb)/2+1;
        double mid = 0;
        double midafter=0;
        while (ai < a.length && bi < b.length && k > 0) {
            mid=midafter;
            midafter = (a[ai] < b[bi]) ? a[ai++] : b[bi++];  
            k--;  
        }  
        while (ai < a.length && k > 0) { 
            mid=midafter;
            midafter = a[ai++];  
            k--;  
        }  
        while (bi < b.length && k > 0) {  
            mid=midafter;
            midafter = b[bi++];  
            k--;  
        }  
        return (lena+lenb)%2==0?(mid+midafter)/2:midafter;  
    } 

 12.判断某个数组分成n段,每段的和相同

这里是三段

就是遍历一遍找出那个除之后的值,然后遍历一遍

public boolean isEqual_3(int[] a) {
        int n=a.length;
        int sum=0;
        for(int i=0;i<n;i++) sum+=a[i];
        
        if(sum%3!=0) return false;
        int help=sum/3;
        int temp=0;
        int item=0;
        int i;
        for(i=0;i<n;i++) {
            temp+=a[i];
            if(temp==help) {
                item++;
                temp=0;
            }
            
        }
        if(item==3&&i==n) return true;
        else return false;
    }

 13.一个包含数字、字母和小数点的字符串,找到数值最大的子串。如123.456.789找出789,123.456.123找出456.123

目前的理解是先把字母分出来。再根据.分开组合再排序

public class Main {   
    public static void main(String[] args) {  
        Scanner sc = new Scanner(System.in);   
        String str=sc.nextLine();
        Stack<String> stack=new Stack<>();
        int top=0;//表示当前顶部是不是.
        double d=0;
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<str.length();i++) {
            if(str.charAt(i)>='a'&&str.charAt(i)<='z') {
                if(sb.length()!=0) {
                    stack.add(sb.toString());
                    sb.setLength(0);
                }               
                continue;
            }
            else if(str.charAt(i)=='.')
            {
                if(sb.length()!=0&&sb.charAt(sb.length()-1)=='.') {//这里主要为了防止连续.的问题
                    stack.add(sb.toString());
                    sb.setLength(0);
                }
                else {
                    sb.append(str.charAt(i));
                }      
            }
            else
            {
                sb.append(str.charAt(i));
            }
        }
        String[] res=new String[stack.size()];
        int i=0;
        while(!stack.isEmpty()) {
            res[i++]=maxString(stack.pop());           
        }
        Arrays.sort(res,new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                // TODO Auto-generated method stub
                return (int) (Double.parseDouble(o1)-Double.parseDouble(o2));
            }
        });
        System.out.println(res[res.length-1]);
    }  
    public static String maxString(String str) {
        String help[]=str.split("\\.");
        String[] get=new String[2*help.length-1];
        for(int i=0;i<help.length;i++) {
            get[i]=help[i];
        }
        for(int i=0;i<help.length-1;i++) {
            get[i+help.length]=help[i]+"."+help[i+1];
        }       
        Arrays.sort(get);
        return get[get.length-1];
    }
}

 14.题目描述:S[i] 表示一个集合,集合的第一个元素是 A[i],第二个元素是 A[A[i]],如此嵌套下去。求最大的 S[i]。

Input: A = [5,4,0,3,1,6,2]
Output: 4
Explanation:
A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.
One of the longest S[K]:
S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}
public int arrayNesting(int[] nums) {
    int max = 0;
    for (int i = 0; i < nums.length; i++) {
        int cnt = 0;
        for (int j = i; nums[j] != -1; ) {
            cnt++;
            int t = nums[j];
            nums[j] = -1; // 标记该位置已经被访问
            j = t;

        }
//这里遍历完了没有重置,是因为这是一个循环的,所以就算后面的去遍历结果仍然是一样的 max
= Math.max(max, cnt); } return max; }

15.

Input: arr = [1,0,2,3,4]
Output: 4
Explanation:
We can split into two chunks, such as [1, 0], [2, 3, 4].
However, splitting into [1, 0], [2], [3], [4] is the highest number of chunks possible.

题目描述:分隔数组,使得对每部分排序后数组就为有序。(求最大的分割组)

public int maxChunksToSorted(int[] arr) {
    if (arr == null) return 0;
    int ret = 0;
    int right = arr[0];
    for (int i = 0; i < arr.length; i++) {
        right = Math.max(right, arr[i]);
        if (right == i) ret++;//每遇到一个当前分组最大的才加一
    }
    return ret;
}

16.判断两个字符串的字母是不是都相同

public boolean isAnagram(String s, String t) {
    int[] cnts = new int[26];
    for (char c : s.toCharArray()) {
        cnts[c - 'a']++;
    }
    for (char c : t.toCharArray()) {
        cnts[c - 'a']--;
    }
    for (int cnt : cnts) {
        if (cnt != 0) {
            return false;
        }
    }
    return true;
}

17.判断是否为同构字符串,每次记录同一个字符前一次的位置,然后比较

public boolean isIsomorphic(String s, String t) {
        int[] preIndexOfS = new int[256];
        int[] preIndexOfT = new int[256];
        for (int i = 0; i < s.length(); i++) {
            char sc = s.charAt(i), tc = t.charAt(i);
            if (preIndexOfS[sc] != preIndexOfT[tc]) {
                return false;
            }
            preIndexOfS[sc] = i;
            preIndexOfT[tc] = i;
        }
        return true;
}

18.判断一个数是不是回文数:

public boolean isPalindrome(int x) {
        if (x == 0) {
            return true;
        }
        if (x < 0 || x % 10 == 0) {
            return false;
        }
        int right = 0;
        while (x > right) {//只取后一半
            right = right * 10 + x % 10;
            x /= 10;
        }
        return x == right || x == right / 10;
}

 19.求最大公约数

public static int getGCD(int a, int b) {
    if (a < 0 || b < 0) {
        return -1; // 数学上不考虑负数的约数
    }
    if (b == 0) {
        return a;
    }
    while (a % b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    return b;
}

 20.一个n位数,现在可以删除其中任意k位,使得剩下的数最小

//找到最小的下标
public
int Find_min(int[] a,int start,int end) { int minIndex=start; for(int i=start;i<=end;i++) { if(a[i]<a[minIndex]) { minIndex=i; } } return minIndex; } int getRemain(int arr[], int size, int k) { int revIndex=-1; int res=0; for(int i = size - k; i < size; ++i) { revIndex = Find_min(arr, revIndex + 1, i);//注意i的大小变化 res = res * 10 + arr[revIndex]; } return res; }

 

posted @ 2019-04-15 20:31  LeeJuly  阅读(220)  评论(0)    收藏  举报