LeetCode刷题笔记之hot 100(二)

1. 322【零钱兑换】- 动态规划

  • 题目: 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。
  • 代码:
class Solution {
    public int coinChange(int[] coins, int amount) {
        //amount相当于书包的总容量,coins相当于每块石头
        //bp表示凑成总金额所需的最少的硬币个数
        //dp[j] = min(dp[j],dp[j-coins[i]]+1)
        //dp[0]=0,dp[]=amount+1
        if(amount==0) return 0;
        int[] dp = new int[amount+1];
        Arrays.fill(dp,amount+1);
        dp[0] = 0;

        for(int i=0;i<coins.length;i++){
            for(int j=1;j<=amount;j++){
                if(coins[i]<=j){
                    dp[j] = Math.min(dp[j],dp[j-coins[i]]+1);
                }
            }
        }
        return dp[amount]>amount?-1:dp[amount];

    }
}

2. 33【搜索旋转排序数组】- 二分查找

  • 题目: 整数数组 nums 按升序排列,数组中的值 互不相同 。
    在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
    给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
    你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
  • 代码:
class Solution {
    public int search(int[] nums, int target) {
        //二分查找
        if(nums.length == 1) return nums[0]==target?0:-1;
        int left = 0;
        int right = nums.length-1;

        while(left<=right){
            int mid = left+(right-left)/2;
            if(nums[mid] == target) return mid;
            //[0,mid]是递增的
            if(nums[0]<=nums[mid]){
                if(nums[mid]>target && nums[0]<=target){
                    right = mid - 1;
                }else{
                    left = mid + 1;
                }
            }else{//[mid,len]是递增的
                if(nums[mid]<target && nums[nums.length-1]>=target){
                    left = mid+1;
                }else{
                    right = mid-1;
                }
            }
        }
        return -1;
    }
}

3. 215【数组中的第k个最大元素】- 优先级队列

  • 题目: 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
  • 代码:
class Solution {
    public int findKthLargest(int[] nums, int k) {
        //使用优先级队列,使用大根堆排序,返回第k个元素
        PriorityQueue<Integer> heap = new PriorityQueue<>(new Comparator<Integer>(){
            public int compare(Integer a,Integer b){
                return b-a;
            }
        });
        for(int i=0;i<nums.length;i++){
            heap.offer(nums[i]);
        }
        int ans=0;
        for(int i=0;i<k;i++){
            ans = heap.poll();
        }
        return ans;
    }
}

4. 46【全排列】- 回溯算法

  • 题目: 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
  • 代码:
class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        //典型的回溯算法
        boolean[] isUsed = new boolean[nums.length];
        Arrays.fill(isUsed,false);
        backtrack(nums,isUsed);
        return ans;
    }
    public void backtrack(int[] nums,boolean[] isUsed){
        if(path.size() >= nums.length){
            ans.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(isUsed[i]) continue;
            path.add(nums[i]);
            isUsed[i] = true;
            backtrack(nums,isUsed);
            path.removeLast();
            isUsed[i] = false;
        }
    }
}

5. 55【跳跃游戏】- 贪心算法

  • 题目: 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
    判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
  • 代码:
class Solution {
    public boolean canJump(int[] nums) {
        //每次跳跃选择最大跳跃范围,遍历这个范围内的每一个位置
        //重复上述操作,检查是否能够到达最后一个位置
        if(nums.length == 1) return true;
        int loc = nums[0];
        for(int i=0;i<=loc;i++){
            if(nums[i]+i > loc){
                loc = nums[i]+i;
            }
            if(loc>=nums.length-1){
                return true;
            }
        }
        return false;
    }
}

6. 5【最长回文子串】- 动态规划

  • 题目: 给你一个字符串 s,找到 s 中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
  • 代码:
class Solution {
    public String longestPalindrome(String s) {
        //dp[i][j]表示substring(i,j+1)是否是回文串
        //dp[i][j] = true(s[i]==s[j]) or false(s[i]!=s[j])
        //dp[i][j] = true(s[i]==s[j] and j-i<=1 or dp[i+1][j-1])

        if(s.length()==1) return s;
        int n = s.length();
        boolean[][] dp = new boolean[n][n];
        int index = 0;
        int len = 0;
        for(int i=n-1;i>=0;i--){
            for(int j=0;j<n;j++){
                if(s.charAt(i) == s.charAt(j)){
                    if(j-i<=1){
                        dp[i][j] = true;
                    }else if(dp[i+1][j-1]){
                        dp[i][j] = true;
                    }
                    if(dp[i][j] && len < j-i+1){
                        index = i;
                        len = j-i+1;
                    }
                }else{
                    dp[i][j] = false;
                }
            }
        } 
        return s.substring(index,index+len);
   }
}

7. 22【括号生成】- 回溯算法

  • 题目: 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
  • 代码:
class Solution {
    List<String> ans = new ArrayList<>();
    StringBuilder sb = new StringBuilder();
    public List<String> generateParenthesis(int n) {
        //回溯法:左右括号的个数<=n,且右括号个数<左括号
        //当字符串的长度==2*n是终止
        backtrack(0,0,n);
        return ans;
    }
    public void backtrack(int left,int right,int n){
        if(sb.length() == 2*n){
            ans.add(sb.toString());
            return;
        }
        if(left < n){
            sb.append('(');
            backtrack(left+1,right,n);
            sb.deleteCharAt(sb.length()-1);
        }
        if(right<left){
            sb.append(')');
            backtrack(left,right+1,n);
            sb.deleteCharAt(sb.length()-1);
        }
    }
}

8. 39【组合总和】- 回溯算法

  • 题目: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
    candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
    对于给定的输入,保证和为 target 的不同组合数少于 150 个。
  • 代码:
class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    List<Integer> path = new LinkedList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        //回溯算法
        backtrack(candidates,target,0,0);
        return ans;
    }
    public void backtrack(int[] candidates, int target,int index,int sum){
        if(index>=candidates.length||sum>target)
            return;
        if(sum == target){
            ans.add(new ArrayList(path));
            return;
        }
        
        for(int i=index;i<candidates.length;i++){
            path.add(candidates[i]);
            sum += candidates[i];
            backtrack(candidates,target,i,sum);
            path.removeLast();
            sum -= candidates[i];
        }
    }
}

9. 48【旋转图像】- 数组/双指针

  • 题目: 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
    你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
  • 代码:
class Solution {
    public void rotate(int[][] matrix) {
        //第i行变成第n-i-1列,第j列变成第j行
        //首先,按行对数组进行反转
        //然后,以对角线为轴交换两边元素
        int n = matrix.length;
        int left = 0;
        int right = n-1;
        int tmp;
        while(left<right){
            for(int j=0;j<n;j++){
                tmp = matrix[left][j];
                matrix[left][j] = matrix[right][j];
                matrix[right][j] = tmp;
            }
            left++;
            right--;
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<i;j++){
                tmp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = tmp;
            }
        }
    }
}

10. 53【最大子数组和】- 动态规划

  • 题目: 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
    子数组是数组中的一个连续部分。
  • 代码:
class Solution {
    public int maxSubArray(int[] nums) {
        //dp[i]表示以nums[i]为结尾的最大子数组和
        //dp[i] = Math.max(dp[i-1]+nums[i],nums[i])
        //dp[0] = nums[0]
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        int max = nums[0];
        for(int i=1;i<n;i++){
            dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
            max = Math.max(dp[i],max);
        }
        return max;
    }
}
  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值