大水题集合
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; }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10712887.html

浙公网安备 33010602011771号