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

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

三.数组

 

四.堆、栈、序列

 

五.链表

 

六.哈希与映射

 

七.树

 

八.排序与检索

 

九.动态规划

 

十.图论

 

十一.数学&位运算

 

十二.模拟面试

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值