新手小白从零开始的刷题之路,边刷题边学习编程语言~只记录思路不记录源码。
两数相加
循环外:
carry
:存储进位,值为0或1
l3
:结果链表头结点ListNode l3 = new ListNode(0);
curr
:结果链表操作节点
while循环的判定条件为l1
或l2
当前节点不为null
while循环内:
val1
:存储l1
当前节点的值,若l1为null,则赋值为0
val2
:存储l2
当前节点的值,若l2为null,则赋值为0
sum
:sum = carry + val1 + val2
,结果链表当前位的值,需要对该值作%10
计算来得出新的carry值
需要进行的操作:
- 判断
l1
,l2
当前结点是否为null, - 计算
sum = carry + val1 + val2
- 计算进位
carry = sum / 10
- 实例化
l3
的下一个结点curr.next = new ListNode(sum % 10)
- 结点移动
- 如果
l1
,l2
都已走完,注意看是否仍有进位 - 返回
l3
的next,因为头结点为0
注意ListNode是结点不是链表
赋值的时候要判断l1
,l2
是否为null
无重复字符的最长子串
一般遇到这种元素+索引的,都可以用HashMap来优化。这道题目的主要解决思路是滑动窗口。
HashMap常用方法:
//实例化
Map< Character, Integer > map = new HashMap<>();
//获取key的索引
map.get(key);
//判断map中是否包含key
map.contansKey(key);
//将key,index添加到map里
map.put(key,index);
//从String里取字符
string.charAt(index);
//判断HashSet里是否包含某元素
set.contains(x);
//将某元素加入set
set.add(x);
取窗口[i,j)
,判断j
所指的字符是否与窗口内某字符相同,如果是的话,直接将窗口移至相同的字符后一位,所以,保存map.put(s.charAt(j), j+1)
,即直接将相应字符的索引保存为其下一位,这样可以直接map.get(x)
来取到窗口需要移动至的位置。
这里还需要注意,map里保存了已遍历的所有元素,所以在已保存元素x
后,如果窗口滑动至x
右侧,为了保证继续遍历检测时,即使遇到又一个x
也不会因为map.get(s.charAt(j))
而使i
左移,所以要判断此时窗口的左边界i
与map.get()
获得的值哪个更大。比如,重复....x....重复..i...x
,此时窗口应该已移至第二个重复
右侧,即左边界为i
所指的地方,如果j
继续后移,遇到第二个x
,那么会让map.contansKey(s.charAt(j))
判断为true
,此时应当比较i
和map.get(s.charAt(j))
的大小,避免取到之前的第一个x
的位置。因为这个x
在新的子串中并没有重复,所以应该保持i
的位置,继续j++
。
寻找两个有序数组的中位数
这是按顺序刷题遇到的第一个难题,相当于找两个有序数组合并后的第k个元素。很难理解,对于一些条件的考虑判断还不是很全面,尤其是对k到底应该+1还是-1很迷惑。
输入a,b两个数组,为方便表述,另设两数组合并后的有序数组为c,先将可能遇到的情况列举出来:
- 其中一个数组为空:则返回另一个数组的中位数(注意数组长度奇偶,见2)
- 数组总长度为奇数:返回
c[c.length/2+1]
;数组总长度为偶数:返回(c[c.length/2]+c[c.length/2-1])/2.0
。需要注意的几点:c的中位数的数组下标是 奇—长度/2+1 偶—长度/2&长度/2-1,而我们解题思路中的k意为“第k个”,如果需要根据k取下标,应使用k-1才能取到第k个元素的值。
k到底是什么?
找中位数=找合并后有序数组的第k个元素,当数组c长度为奇数时,需要找的是第k=c.length/2+1个元素,该元素的数组下标为c.length/2,即k-1;当数组c长度为偶数时,需要找的是第k=c.length/2-1个元素,和第k=c.length/2个元素,该元素的数组下标则分别为c.length/2和c.length/2+1。
k | 下标 | 下标与k的关系 |
---|---|---|
奇数 | c.length/2+1 | c.length/2 |
偶数 | c.length/2&c.length/2+1 | c.length/2-1&c.length/2 |
如何找到c的中位数?
不需要排序,用二分查找的思想。
若是取第k个,则将k一分为二,先在a里找k/2,在b里找k/2,设目前a数组查询位置为a_begin,b数组查询位置为b_begin根据找到的结果来判断:
- x_begin后移k/2后仍在数组内,没有越界,则将该值赋给mid_x;比较mid_x
mid_a<mid_b | mid_a>mid_b |
---|---|
a_begin后移k/2,正好下一次从后移之后的下一个元素开始查找,这会儿下标多挪了一个也是ok的,就不用-1了。 | b_begin后移k/2。这说明第k个元素应该是在mid_b所处的元素之后的后半部分,或是mid_a以前的部分。 |
总而言之,就是在a中找一个位置,在b中找一个位置,这俩位置加起来正好是k。体现在上述思路中,则是mid所处的那个【位置】
2. x_begin已查询到数组末尾(≥x.length),则k在另一个数组中,另一数组取下标为x_begin+k -1的元素即可得到第k个元素。
3. 如果k为1,取x_begin中较小的那个。
实现
递归调用find_kth方法:find_kth(int[] a, int a_begin, int[] b, int b_begin, int k)
,x_begin根据判断移动位置