leetcode-数组总结

leetcode-26- 删除排序数组中的重复项-java
1 考虑到leetcode测试用例,数组为空和长度为1的情况。
2 java队列最后一个的索引为长度-1,不能用arr[length]。
3 可以认为这个方法是双指针
数组完成排序后,我们可以放置两个指针 i 和index,其中i 是慢指针,而 index 是快指针。只要 nums[i]=nums[index-1],我们就增加i以跳过重复项。
当我们遇到 nums[index-1]≠nums[i]时,跳过重复项的运行已经结束,因此我们必须把它的值复制到 index。然后递增index和i,接着我们将再次重复相同的过程,直到i 到达数组的末尾为止。

leetcode-122-买卖股票的最佳时机 II-java
1 有时候数组循环处理,从前往后很麻烦,从后往前很简单
2 我们可以简单地继续在斜坡上爬升并持续增加从连续交易中获得的利润,而不是在谷之后寻找每个峰值。最后,我们将有效地使用峰值和谷值,但我们不需要跟踪峰值和谷值对应的成本以及最大利润,但我们可以直接继续增加加数组的连续数字之间的差值,如果第二个数字大于第一个数字,我们获得的总和将是最大利润。这种方法将简化解决方案。

leetcode-189-旋转数组( Rotate Array)-java
1 使用一个大小为k的数组,保存0-k-1位的数字,然后将k到length-1位的数字按照index=(i+k) mod length 为新位置摆放,然后将temp数组放入新位置
2 因为反转用的空间只用一个变量即可(或者不用也行,使用位运算即可)
将数组分为两部分,分为0——length-k-1和length-k——length-1; 两部分分别反转,再整体反转,就能得到正确的结果。 例子:[1,2,3,4,5,6,7] 和 k = 3 分为[1,2,3,4]和[5,6,7];分别反转后得到[4,3,2,1,7,6,5] 再整体反转得[5,6,7,1,2,3,4] 即为正确得结果
每个数原来应该在的位置是(i+k) mod length
0——length-k-1 就是 length-k-i 再反转 k+i
length-k——length-1 就是 length*2-k-i ,再反转 k+i-length
这两个就是(i+k) mod length

nums = “----->–>”; k =3
result = “–>----->”;
reverse “----->–>” we can get “<–<-----”
reverse “<–” we can get “–><-----”
reverse “<-----” we can get “–>----->”

如果需要额外空间的(移动x位的),可以考虑多次反转

方法一中使用额外数组的原因在于如果我们直接将每个数字放至它最后的位置,这样被放置位置的元素会被覆盖从而丢失。因此,从另一个角度,我们可以将被替换的元素保存在变量temp中,从而避免了额外数组的开销。
我们从位置0开始,最初令temp=nums[0]。根据规则,位置0的元素会放至(0+k) mod n的位置,令x=(0+k) mod n,此时交换temp和nums[x],完成位置x的更新。然后,我们考察位置x,并交换temp和nums[(x+k) mod n],从而完成下一个位置的更新。不断进行上述过程,直至回到初始位置0。
容易发现,当回到初始位置0时,有些数字可能还没有遍历到,此时我们应该从下一个数字开始重复的过程,可是这个时候怎么才算遍历结束呢?我们不妨先考虑这样一个问题:从0开始不断遍历,最终回到起点0的过程中,我们遍历了多少个元素?

由于最终回到了起点,故该过程恰好走了整数数量的圈,不妨设为a圈;再设该过程总共遍历了b个元素。因此,我们有an=bk,即an一定为n和k的公倍数。又因为我们在第一次回到起点时就结束,因此a要尽可能小,故an就是n,k的最小公倍数lcm(n,k),因此b就为lcm(n,k)/k。
这说明单次遍历会访问到lcm(n,k)/k个元素。为了访问到所有的元素,我们需要进行遍历的次数为gcd(n,k)
其中gcd指的是最大公约数。
如果读者对上面的数学推导的理解有一定困难,也可以使用另外一种方式完成代码:使用单独的变量 count 跟踪当前已经访问的元素数量,当 count=n时,结束遍历过程。

leetcode-217-存在重复元素(Contains Duplicate)-java
有时候考虑到重复,可以采用set数据结构
重复的时候,有时候可以使用计数排序的思想,创建一个新数组来计数
这个方法按道理,时间复杂度和set是一样的,还要遍历两次,但是之所以快,可能是hashset内部操作虽然是O(1),但是又几部操作,比计数排序每位只做三个操作慢

leetcode-136-只出现一次的数字(single number)-java
面对重复的问题,如果对空间有限制,可以考虑位运算,尤其是亦或,而且位运算往往很巧妙,速度很快
异或,xor
(a^b) ^b=a ,而且满足交换律

leetcode-350-两个数组的交集 II( Intersections of two arrays II)-java
1 如果数组中元素重复的有多个,可以考虑用map装起来,key为数组中的数,对应的value为数的个数
2 可以采用排序的算法,先用array的方法排序,再使用双指针算法比较,
相等则加入list,两个指针各自向后移1位
哪个小,就小的对应指针向后移1位
速度比之前快,主要是如果一方的长度很小,有可能可以很快算完(一方结束即可)
3 计数排序在面对重复的问题,可以一定程度上代替hashmap,但是计数排序的长度为max-min+1,如果max-min是int的max和min,得到的长度会超过int,成为负数,因为java中数组的长度最大是int的max,不能超过它

leetcode-66-加一(PLUS one)-java
注意for循环到最后一个时,那个i++,i–也要执行一次,执行完才让i不符合范围。
新建一个1000型的数组(新建后,设置1就可以,之后不用设置0,因为创建是就为0)
判断+1进位可以用mod10

leetcode-283-移动零(remove zeroes)-java
1 如果在程序中每次循环都要操作一个东西,可以试试在最后一次性一块操作。
2 将所有 0 移动到数组末尾。
所有非零元素必须保持其原始顺序。
这里很好地认识到这两个需求是相互排斥的,也就是说,你可以解决单独的子问题,然后将它们组合在一起以得到最终的解决方案。
这种方法即先满足一个需求,然后满足另一个需求。它以一种巧妙的方式做到了这一点。上述问题也可以用另一种方式描述,“将所有非 0 元素置于数组前面,保持它们的相对顺序相同”。
3 当我们遇到一个非零元素时,我们需要交换当前指针和慢速指针指向的元素,然后前进两个指针。如果它是零元素,我们只前进当前指针。

leetcode-1-两数之和(two sum)-java
如果要查找数组中某个值和值的index的话,可以先把数组,以值为key,index为value,插入hashmap,要的时候map.get(值)

leetcode-36- 有效的数独(valid sudoku)-java
查找数组中重复数字,可用
hashmap(如果数字很多,需要index)
hashset(如果数字很多,不需要index)
计数排序(数字要在一定范围内,不能超过integer.max_value,要几个,用int[],只要一个,用boolean[])
位运算(只能算出重复1个)(如果只用一个int,数字浮动在0-32之内),相当于BitMap,这个可以范围很大

九宫格,先算出左上角顶点,然后for循环i 3次,j 3次。(正推)
如何算出顶点,第一个for循环indexi 3次(每次+3),indexj也一样
或者k从0循环9次,indexi =(k%3)3;indexj=k-begini/3;
或者从i,j
倒推*第几个九宫格, box_index = (row / 3) * 3 + columns / 3(直接设置9个数组,遍历81个元素,直接放入对应数组。)

leetcode-48-旋转图像(rotate image)-java
对于矩阵,图像旋转等位置变化的问题,最关键的要点就是每个点具体位置变化的点,从哪里来,到哪里去
解决这个问题,
首先可以考虑对称的方法,针对某个关键点或者关键的线进行对称
如果找不到对称的方法,可以具体考虑点变化的规律,可以找到几个实例点,研究前后位置的变化
还可以将绝对坐标与相对坐标进行转化,研究针对某个点的坐标变化

leetcode-384-打乱数组(shuffle an array)-java
在class中设置一个int数组作为源头,一个int数组作为打乱的数组返回
reset方法,返回一个copy的数组
shuffle方法,将打乱的数组再次打乱后返回,
Fisher-Yates 洗牌算法跟暴力算法很像。在每次迭代中,生成一个范围在当前下标到数组末尾元素下标之间的随机整数。接下来,将当前元素和随机选出的下标所指的元素互相交换 - 这一步模拟了每次从 “帽子” 里面摸一个元素的过程,其中选取下标范围的依据在于每个被摸出的元素都不可能再被摸出来了。此外还有一个需要注意的细节,当前元素是可以和它本身互相交换的 - 否则生成最后的排列组合的概率就不对了。

leetcode-15-三数之和(3sum)-java
解法1:
数组排序后,先确定两个数,再从set中确定是否有对应的第三个数
设置set,将所有的数字都放入set。
然后将数组排序。
先计算,两个负数,一个正数的情况,双指针计算完所有的负数的情况,根据set是否有对应正数来确定是否组合存在。
再计算两个正数,一个负数的情况。这时,注意三个0的情况
解法2:
先确定一个数,再从排序后的数组从头到尾,双指针,确定是否有两个数的和为对应的数
首先对数组进行排序,排序后固定一个数 nums[i],再使用左右指针指向 nums[i]后面的两端,数字分别为 nums[L]和 nums[R],计算三个数的和 sum判断是否满足为 0,满足则添加进结果集
如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环
如果 nums[i] =nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
当 sum=0 时,nums[L]= nums[L+1] 则会导致结果重复,应该跳过,L++
当 sum= 0 时,nums[R]= nums[R−1]则会导致结果重复,应该跳过,R−−

leetcode-73- 矩阵置零(set matrix zeroes)-java
使用固定的空间,原地算法

其实我们可以利用首行首列来表示这一行,

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值