JAVA刷力扣《算法面试题汇总》

    科技2022-08-12  104

    JAVA刷力扣《算法面试题汇总》

    一.开始之前 

    1.找出只出现一次的数字,其余均为两次

    异或运算(^)就行了。

    2.多数元素(次数多于n/2的元素,假设数组中一定存在)

    (1)排序法:中间位置

    先排序Array.sort(nums),然后取nums[nums.length/2]

    class Solution { public int majorityElement(int[] nums) { Arrays.sort(nums); return nums[nums.length/2]; } }

    (2)摩尔投票法

    多数元素比其他所有元素加起来都多,所以投票法mode可以抓到多数元素。

    a、假如mode直接抓到了多数元素,则一个多数元素消掉一个非多数元素,最后留下的肯定是多数元素。

    b、假如没有抓到多数元素,也不会使多数元素减少,只会使非多数元素减少,最后留下的还是多数元素。

    class Solution { public int majorityElement(int[] nums) { //1.初始化 int mode=0; int vote=0; //2.遍历 for(int num:nums){ //更新mode if(vote==0){ mode=num; } //更新vote if(num==mode){ vote++; }else{vote--;} } return mode; } }

    3.有序矩阵找元素

    熟悉以下java关于矩阵的声明于遍历(矩阵也是二维数组)

    class Solution { public boolean searchMatrix(int[][] matrix, int target) { //搞定特殊用例:空矩阵 if (matrix.length == 0 || matrix[0].length == 0) { return false; } //右上角开始,小了行数++,大了列数-- int row = 0; int col = matrix[0].length - 1; while (row < matrix.length && col >= 0) { if ( matrix[row][col]<target) { row++; } else if (matrix[row][col]>target) { col--; } else { return true; } } return false; } }

    4.合并有序数组:把nums2合并到nums1中,升序。(不能开新的数组)

    python中可以直接对数组pop、append,把数组当作栈或队列用,java不行。

    java的栈、数组、列表不是同一个东西,数组不能直接pop、append。

    class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { //先归并大的,这样一遍扫面即可。 for(int k = m+n-1,i = m-1,j = n-1;k >= 0;k--) { if(i < 0) { nums1[k] = nums2[j--]; continue; } if(j < 0) { nums1[k] = nums1[i--]; continue; } if(nums1[i] >= nums2[j]) nums1[k] = nums1[i--]; else nums1[k] = nums2[j--]; } } }

    5.丢鸡蛋(困难)

    最坏情况下的移动次数。

    动态规划

    class Solution { public int superEggDrop(int K, int N) { if (N == 1) { return 1; } int[][] f = new int[N + 1][K + 1]; for (int i = 1; i <= K; ++i) { f[1][i] = 1; } int ans = -1; for (int i = 2; i <= N; ++i) { for (int j = 1; j <= K; ++j) { f[i][j] = 1 + f[i - 1][j - 1] + f[i - 1][j]; } if (f[i][K] >= N) { ans = i; break; } } return ans; } }

    二.字符串

    1.验证回文串

    移动双指针,遇到不同的返回false;一直相同,直到i、j相遇则返回true。

    class Solution { public boolean isPalindrome(String s) { int i = 0, j = s.length() - 1; while(i < j){ //i,j位置不是字符则直接移动 while(i < j && !Character.isLetterOrDigit(s.charAt(i))) i++; while(i < j && !Character.isLetterOrDigit(s.charAt(j))) j--; if(Character.toLowerCase(s.charAt(i)) != Character.toLowerCase(s.charAt(j))) return false; i++; j--; } return true; } }

    2.分割回文串

    把一个字符串全部拆分为‘回文串’,每一种拆法为一个List。

    然后把所有拆法都放进一个大的List中,形成二维List输出。

    import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; public class Solution { public List<List<String>> partition(String s) { int len = s.length(); List<List<String>> res = new ArrayList<>(); if (len == 0) { return res; } // Stack 这个类 Java 的文档里推荐写成 Deque<Integer> stack = new ArrayDeque<Integer>(); // 注意:只使用 stack 相关的接口 Deque<String> stack = new ArrayDeque<>(); backtracking(s, 0, len, stack, res); return res; } /** * @param s * @param start 起始字符的索引 * @param len 字符串 s 的长度,可以设置为全局变量 * @param path 记录从根结点到叶子结点的路径 * @param res 记录所有的结果 */ private void backtracking(String s, int start, int len, Deque<String> path, List<List<String>> res) { if (start == len) { res.add(new ArrayList<>(path)); return; } for (int i = start; i < len; i++) { // 因为截取字符串是消耗性能的,因此,采用传子串索引的方式判断一个子串是否是回文子串 // 不是的话,剪枝 if (!checkPalindrome(s, start, i)) { continue; } path.addLast(s.substring(start, i + 1)); backtracking(s, i + 1, len, path, res); path.removeLast(); } } /** * 这一步的时间复杂度是 O(N),因此,可以采用动态规划先把回文子串的结果记录在一个表格里 * * @param str * @param left 子串的左边界,可以取到 * @param right 子串的右边界,可以取到 * @return */ private boolean checkPalindrome(String str, int left, int right) { // 严格小于即可 while (left < right) { if (str.charAt(left) != str.charAt(right)) { return false; } left++; right--; } return true; } }

    三.数组

     

    四.堆、栈、序列

     

    五.链表

     

    六.哈希与映射

     

    七.树

     

    八.排序与检索

     

    九.动态规划

     

    十.图论

     

    十一.数学&位运算

     

    十二.模拟面试

     

    Processed: 0.010, SQL: 8