第一题 287. Find the Duplicate Number
算法
这道题是非常有意思的一题,由于题目要求不能够改变Array本来的结构,相当于只是read形式的,所以另一道相似题目用的转负442 Find All Duplicates in an Array的方法就暂时用不了了。
在这道题中,我们要使用的在链表中求环的方式来进行这道题目的求解。由于题目中已经说明必定存在一个环,那么我们可以将环想象成以下样子的。
(Start) (Circle-Entry)
| |
----->----@---->-----------
| |
| |
^ |
| |
|-------@--<----|
|
(Meet-Point)
想要求得重复的数值,我们利用两个指示点(fast, slow),通过两部来完成整个
第一步 检验是否为环形,并得到两个点相遇的位置
我们首先获得两个指示点fast, slow。在这个Array中,每当slow走一步,fast走的总是他的两倍。这样当进入环形之后,就可以看做一个龟兔赛跑,快的兔子总会在某个点追上比较慢的乌龟,即slow == fast, 这个点我们叫相遇点(Meet-Point)。
第二步 找到进入圆环的那个点
为了找到进入圆环的点,我们需要进行一些数学推到。
令:
- L1: 开始(Start) 到进入圆圈的点(Circle-Entry)距离
- L2: 进入圆圈的点(Circle-Entry)到相遇点(Meet-Point)距离
- C: 圆环周长
- n: 当两个指示点相遇的时候,快的那个走的圈数
根据我们的定义,我们可以知道:
- 当相遇的时候,slow走的距离为L1 + L2
- 当相遇的时候, fast走的距离为L1 + L2 + C*n
由于我们知道,每当slow走一步,fast总是走两步的,所以
2 (L1+L2) = L1 + L2 + n C
=> L1 + L2 = n C
=> L1 = (n - 1) C + (C - L2)
当我们忽视n-1 * C的时候(走多少圈都不影响相遇点的位置(Meet-Point))
我们得到了 L1 = C - L2
这意味着如果我们两个指针,一个从Start开始出发,另一点从相遇点(Meet-Point)开始出发,当行走相同的距离的时候(L1)。从Start开始那个点会到达圆圈起始点(Circle-Entry), 而从相遇点(Meet-Point)开始出发的那个点,也会刚好走完一整圈,到达圆圈起始点(Circle-Entry)。
这个时候我们就得到了相遇点,以下是代码具体的实现
第二题 142. Linked List Cycle II
算法
方法与第一题相似, 只不过这题是在一个链表的基础上求解问题
第三题 141. Linked List Cycle
算法
更为简单,只需要判断是否有circle即可
第四题 189. Rotate Array
算法
方法一
nums = [1,2,3,4,5,6,7] and k = 3
- 首先旋转0 , length - k -1部分 [1,2,3,4] => [4,3,2,1]
- 然后再旋转剩余部分 [5,6,7] => [7,6,5]
- 之后旋转整个Array [4,3,2,1,7,6,5] => [5,6,7,1,2,3,4]12345678910111213141516171819public class rotate189 {//方法2 O(n), O(1)public void rotate2(int[] nums, int k) {if (nums.length < 2 || nums == null) return;k %= nums.length;reverse(nums, 0, nums.length - k - 1);reverse(nums, nums.length - k, nums.length - 1);reverse(nums, 0, nums.length - 1);}public void reverse(int[] nums, int start, int end) {while(start < end) {int temp = nums[start];nums[start] = nums[end];nums[end] = temp;start++; end--;}}}
方法二
利用额外的存储空间进行存储
自己这个存储可以优化,实际上只需要k单位的存储空间就够了
第五题 151. Reverse Words in a String
算法
方法一
将String 劈开,然后从后向前你用String Builder存储结果
方法二
你用Arrays.asList的颠倒功能,以及String.join, 完成倒序
学到的东西
String.join
String.join(“-“,”string”,”join”) => string-join,后面可以为一个Array
trim()
去除String头和尾的空格,防止出现异常
Collections.reverse(Arrays.asList(words));
除了reverse之外,还有sort等等很多的用法
第六题186. Reverse Words in a String II
算法
与第四题的思路相似,都是通过多次翻转,在不需要更多空间的情况下,完成整个数组的翻转。
可以先进行部分或者整体翻转,然后再进行多次翻转,看结果
第七题228. Summary Ranges
算法
从头向后推进,然后看是不是满足递增1的情况,不是的话就进行输出。但是要注意最后结尾的特殊处理。时间复杂度为O(n)