从零开始LeetCode刷题日记Day1

新手小白从零开始的刷题之路,边刷题边学习编程语言~只记录思路不记录源码。

两数相加

循环外:

carry:存储进位,值为0或1
l3:结果链表头结点 ListNode l3 = new ListNode(0);
curr:结果链表操作节点
while循环的判定条件为l1l2当前节点不为null

while循环内:

val1:存储l1当前节点的值,若l1为null,则赋值为0
val2:存储l2当前节点的值,若l2为null,则赋值为0
sumsum = carry + val1 + val2,结果链表当前位的值,需要对该值作%10计算来得出新的carry值

需要进行的操作:

  1. 判断l1l2当前结点是否为null,
  2. 计算sum = carry + val1 + val2
  3. 计算进位carry = sum / 10
  4. 实例化l3的下一个结点curr.next = new ListNode(sum % 10)
  5. 结点移动
  6. 如果l1l2都已走完,注意看是否仍有进位
  7. 返回l3的next,因为头结点为0

注意ListNode是结点不是链表
赋值的时候要判断l1l2是否为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左移,所以要判断此时窗口的左边界imap.get()获得的值哪个更大。比如,重复....x....重复..i...x,此时窗口应该已移至第二个重复右侧,即左边界为i所指的地方,如果j继续后移,遇到第二个x,那么会让map.contansKey(s.charAt(j))判断为true,此时应当比较imap.get(s.charAt(j))的大小,避免取到之前的第一个x的位置。因为这个x在新的子串中并没有重复,所以应该保持i的位置,继续j++

寻找两个有序数组的中位数

这是按顺序刷题遇到的第一个难题,相当于找两个有序数组合并后的第k个元素。很难理解,对于一些条件的考虑判断还不是很全面,尤其是对k到底应该+1还是-1很迷惑。
输入a,b两个数组,为方便表述,另设两数组合并后的有序数组为c,先将可能遇到的情况列举出来:

  1. 其中一个数组为空:则返回另一个数组的中位数(注意数组长度奇偶,见2)
  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+1c.length/2
偶数c.length/2&c.length/2+1c.length/2-1&c.length/2

如何找到c的中位数?

不需要排序,用二分查找的思想。
若是取第k个,则将k一分为二,先在a里找k/2,在b里找k/2,设目前a数组查询位置为a_begin,b数组查询位置为b_begin根据找到的结果来判断:

  1. x_begin后移k/2后仍在数组内,没有越界,则将该值赋给mid_x;比较mid_x
mid_a<mid_bmid_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根据判断移动位置

参考题解

真正O(log(m+n))的解法,那些说归并排序的别误导人了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值