2020/08/13 探索->初级算法

概述

由LeetCode官方推出的经典面试题目清单,将题目重新整理规划,从而为大家提供更好的练习体验和帮助大家找到理想的工作。将题目分为以下三个部分:

  1. 初级算法-> 帮助入门 自己数了一下有49个题呀
  2. 中级算法-> 巩固训练
  3. 高级算法-> 提升进阶

leetcode网站

数组

1.删除排序数组中的重复项 2020/08/13

在这里插入图片描述
给定一个排序数组,需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组控件,你必须在原地修改数组,并使用O(1)额外空间的条件下完成。
输入:nums =[1,1,2]
函数应该返回新的长度2,并且原数组nums的前两个元素被修改为1,2。

说明:
为什么返回数值是整数,但输出的答案是数组呢?
注意:输入数组是以引用的方式传递的,意味着在函数里修改输入数组对于调用者是可见的。
可以想象内部操作如下:
在这里插入图片描述
目前想法:首先明确,该数组是有序的,并且在原地修改数组数组,使用O(1)的额外空间条件下完成,且不需要考虑超出新长度后面的元素。
感觉挺简单的,由于有顺序,设定一个值用于给数组重新赋值(每当数组当中元素比之前的元素大的时候),最后返回这个值就可以了。
在这里插入图片描述
这个nums没有给定范围是有可能为空数组的,因此需要加判断。
在这里插入图片描述

2.买卖股票的最佳时机 II

在这里插入图片描述
给定了一个数组,其第i个元素是一支给定股票第i天的价格
设计一个算法来计算所获取的最大利润。可以尽可能地完成更多的交易(多次买卖一次股票)。注意:不能同事参与多笔交易。

输入:【7,1,5,3,6,4】
输出:7
解释:第2天买入,第3天卖出,利润为5-1=4.。
第4天买入,第5天卖出,利润为6-3=3。

目前的想法是:定义两个指针i,j(i<j),并且保证2点:prices[i]<prices[j] 和prices[j]>prices[j+1],然后让I=j。现在开始尝试去解答这个题。
最后做出来和开始的想法还是有点不同的。
在这里插入图片描述
看了下别人的题解,可以用暴力、dp、贪心(我这个也是贪心,不过写复杂了)。
大佬写的动态规划代码,对于动态方程的转移太美了。下面记录 下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
我的理解是,就是构建了两个数组,第一个保存第i天所持有的现金,第二个来保存第i天所持有的股票。
所以初始值就是cash[0]=0,hold[0]=-prices[I],因为买了第一天的股票。
然后第二天cash[1] = max(cash[0],hold[0]+prices[1]),比较前一天的最大现金,和将上一天股票抛售所获的的利润和。
hold[1] = max(hold[0],cash[0]-prices[1]),比较前一天所持有的股票和昨天持有的现金买入今天的股票的值。
定义为卖出和买入可能会更好理解一些。

3.旋转数组

2020/08/15 8点53.start
在这里插入图片描述
首先还是第一步,读题:给定了一个数组,将数组中的元素向右移动k个位置,其中k是非负数。
输入:【1,2,3,4,5,6,7】和k=3
输出:【4,5,6,7,1,2,3】
解释:向右旋转1步:【7,1,2,3,4,5,6】
向右旋转2步:【6,7,1,2,3,4,5】
向右旋转3步:【5,6,7,1,2,3,4】

说明:要求想出尽可能多的解决方案,至少有三种步同的方法可以解决这个问题。
要求使用空间复杂度为O(1)的原地算法。

最先想到的算法是之前做杭电oj提供的那种思路:
旋转3次:【7,6,5,4,3,2,1】
【5,6,7】 【1,2,3,4】。
先完成这种方法吧。
没有考虑到nums =[1] k=0 这种情况,也没有考虑到nums=[-1] k=2这种情况。

class Solution {
    public void rotate(int[] nums, int k) {
        k = (k + nums.length)%nums.length;
        if(k > 0 && k<nums.length) {
            // 第一种方法,颠倒数组当中第left和right。
            reverse(nums,0,nums.length-1);
            reverse(nums,0,k-1);
            reverse(nums,k,nums.length-1);
        }
    }
    public void reverse(int[] nums,int left,int right){
        int medium = (right+left)/2;
        int temp;
        for(int i = left; i<= medium; i++){
            temp = nums[i];
            nums[i] = nums[left+right-i];
            nums[left+right-i] = temp;
        }
    }

}

在这里插入图片描述
自己做的第一种方法。
开始没有去考虑k的取值范围,没有去考虑k=0以及k>=nums.length的情况。
考虑以后就是,先把k转为为k=(k+nums.length)%nums.length,然后在分情况考虑。

下面来记录官方给的几种题解:
在这里插入图片描述
还蛮喜欢这种暴力解的思路,旋转k次,每次将数组旋转一个元素(这里用了一个previous来记录每个位置应该放的数,用一个temp来保存当前的值,然后更新这个previous)。

在这里插入图片描述
构建一个额外的数组来将每个元素放到正确的地方,即将原本数组里下标为i的我们把它放到(i+k)%数组的长度的位置。然后把新的数组拷贝到原数组即可。
核心:a[(I+k)%nums.length] = nums[I]。

在这里插入图片描述
在这里插入图片描述
这种方法很巧妙,mark!

4.存在重复元素

2020/08/16 10:02 start
在这里插入图片描述
给定了一个整数数组,判断是否存在重复元素。
如果任意一值在数组中出现至少两次,函数返回true。如果数组中每个元素都不相同,则返回false;

输入:【1,2,3,1】
输出:true

输入:【1,2,3,4】
输出:false

目前想法:构建一个hashset,如果有之前存在的数字,则返回true。。。现在开始尝试写代码。
在这里插入图片描述
这个速度,我人傻了,9ms。
看了别人用的hashes,发现自己就是一个脑瘫。。。直接
这个地方不必要用contains方法,add(object)方法返回都是boolean,如果Set集合中已经包含相同的对象,则不改变Set集合。如果Set集合中不包含添加的对象,则添加对象并返回true,否者返回false。
因此代码可以改为:
在这里插入图片描述
执行时间为6ms。

然后还可以采用sort函数进行排序,然后来判断是否有重复的数字。
采用sort函数,运行时间是4ms。
在这里插入图片描述

然后执行时间为3ms的思路是,首先去获取nums数组中的最大值和最小值,然后新建一个数组(hash)来判断有没有重复元素。
在这里插入图片描述

执行时间为2ms的思路是对每一个元素,判断这个元素与他之前有没有重复的元素。
在这里插入图片描述
1ms和2ms的代码一样,这里不列了。
执行用时为0ms的不列了,本质还是hash。

5.只出现一次的数字

在这里插入图片描述

6.两个数组的交集 II

7.加一

8.移动零

9.两数之和

10.有效的孤独

11.旋转图像

字符串

链表

排序和搜索

动态规划

设计问题

数学

其他

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值