LeetCode刷题记录

数组

求两数之和

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result=new int[2];
        for(int i=0;i<nums.length;i++){
             for(int j=i+1;j<nums.length;j++){
                 if(nums[i]+nums[j]==target){
                     return new int[]{i,j};
                 }
             }
        }
        throw new RuntimeException();
    }
}
时间复杂度:O(n^2)
对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,这将耗费 O(n)O(n) 的时间。
因此时间复杂度为 O(n^2)

需要一种方法,寻找符合要求的元素(target-nums[i])并返回其索引
元素与索引对应最好的方法:哈希表
通过“以空间换时间”的方式,可以将查找时间从O(n)转换为O(1)

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], i);
        }
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (map.containsKey(complement) && map.get(complement) != i) {
                return new int[] { i, map.get(complement) };
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

时间复杂度:O(n)O(n),
我们把包含有 n个元素的列表遍历两次。由于哈希表将查找时间缩短到 O(1),所以时间复杂度为 O(n)。

事实证明:我们用一次遍历就可以完成:在将元素插入表的同时,同时在表中 查找当前元素所对应的目标元素

# 插入表的同时,目标元素一定在当前表么
2357
target 10
##因为此假设:假设每种输入只会对应一个答案,所以数组元素只会存在唯一符合条件的两个元素

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        //查找两个有关联的数字
        //爸爸妈妈问题: 一群人查找爸爸妈妈,来一个人从房间看没有对方则进房间,直到一个人看见对方
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            //链式思维
            if (map.containsKey(complement)) {
                return new int[] { map.get(complement), i };
            }
            map.put(nums[i], i);
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

删除排序数组重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
经验:动态改变数组的下标不可行 移动后指针回退—错误

public int removeDuplicates(int[] nums) {
    //快慢双指针法  把和前一位不同的复制到数组前面
    int j=0;
    for(int i=1;i<nums.length;i++){
        if(nums[i] != nums[i-1]){
             nums[j+1]=nums[i];
             j++;  
        }
    }
    return j+1;
}

最大子序和

暴力法

计算所有连续子数组的和,求最大值

分治法

分治法的精髓在于:
分-----将问题分解为规模更小的子问题;
治-----将这些规模更小的子问题逐个击破;
合-----将已解决的子问题合并,最终得出“母”问题的解;

取数组中心点为中心,最大子序要么全在中心左边,要么在右边,要么跨中心
跨中心的情况:分治成中心点左侧和右侧最大子序和 的问题,再分别用贪心算法
从哪边算意味着(中心算):从哪边连续计数

贪心法

每一步都选最优解,最后就是全局最优方案
遍历数组并更新1. 当期元素 2. 当前元素位置的最大和(currentSum=nums[0]) 3.总的最大和(maxSum=nums[0])
特点:

  1. 局部最优解推到全局最优解。
  2. 只会保留上一步的最优解
    步骤:
  3. 从第二个元素开始遍历,

动态规划

修改数组跟踪当前位置的最大和
遍历数组,更新当前位置的最大和nums[i],全局的最大和maxSum=nums[0]

特点:

  1. 局部最优解推到全局最优解。
  2. 保留之前所有最优解—(以i结尾的最大子序和)

步骤:

  1. 从第二个元素遍历,若前一个(子序和)为正数,才会累加当前数字——>当前最大和
  2. 根据当前最大和求出全局最大和

[-2,1,-3,4,-1,2,1,-5,4]
dp[i]表示以i结尾的最大子序和 dp[i]=max{nums[i],dp[i-1]+nums[i]}
nums[0]>0 nums[1]=nums[1]+nums[0]
nums[1]>0 nums[2]=nums[2]+nums[1]
nums[2]>0 nums[3]=nums[3]+nums[2]

动态规划和贪心算法的异同点:

相同点:

都是通过递推的方式,通过局部最优解来推导全局最优解
贪心算法是动态规划的一种特殊形式

不同点:

贪心算法:

特点是每一步都是局部最优解,只保留上一步的最优解

  1. 动态规划算法:
    特点是每一步
    2.状态转移方程:局部最优解===>全局最优解
    3.边界条件:可直接得出的局部最优解。
## 每次拿能拿的最大的,就是贪心。 
贪心算法最经典的例子,给钱问题。   
比如中国的货币,只看元,有125102050100   
如果我要16元,可以拿161元,82元,但是怎么最少呢?   

如果用贪心算,就是我每一次拿那张可能拿的最大的。   
比如16,我第一次拿20拿不起,拿10元,OK,剩下6元,再拿个5元,剩下1元   
也就是31051
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值