携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情 >>
每日三刷,剑指千题
计划简介:
- 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
- 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
- 每日中午进行编码,时间控制在一小时之内。
- 下班前半小时进行整理总结,并发布到掘金每日更文活动。
说明:
- 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
- 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
- 刷题过程中整理相似题型,刷题模板。
- 目前进度 117/1000 。
[剑指 Offer II 025]链表中的两数相加
给定两个 非空链表 l1和 l2 来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例1:
输入:l1 = [7,2,4,3], l2 = [5,6,4]
输出:[7,8,0,7]
解析
总感觉这个题出的很蠢,其实就是想考反转链表,又套了一个看起来和算法无关的重壳子。
LeetCode 也有很多凑数题,水题,需要我们有一双慧眼。
Code
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Deque<Integer>stack1=new LinkedList<>();
Deque<Integer>stack2=new LinkedList<>();
while (l1!=null){
stack1.push(l1.val);
l1=l1.next;
}
while (l2!=null){
stack2.push(l2.val);
l2=l2.next;
}
ListNode newHead=new ListNode(-1);
int add=0;
while (!stack1.isEmpty()||!stack2.isEmpty()||add!=0){
int sum=add;
sum+=stack1.isEmpty()?0:stack1.poll();
sum+=stack2.isEmpty()?0:stack2.poll();
add=sum/10;
ListNode cur=new ListNode(sum%10);
cur.next=newHead.next;
newHead.next=cur;
}
return newHead.next;
}
}
[725]分隔链表
给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。
每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。
这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。
返回一个由上述 k 部分组成的数组。
示例 1:
输入:head = [1,2,3], k = 5
输出:[[1],[2],[3],[],[]]
解析
这题全是逻辑,没有算法。分情况讨论了:
- k比长度还大的,那必然是每个元素一组,剩下用 null 补上。
- K比长度小,但恰好可以平分的,这个也简单。
- K比长度小,又不能整除的,麻烦了。比如长度为5,分成3份,商是1,余2,剩下的两个怎么处理呢?注意看一句话,
任意两部分的长度差距不能超过 1 。,所以应该分给每一部分1个,就是 2,2,1的分布。
Code
class Solution {
public ListNode[] splitListToParts(ListNode head, int k) {
ListNode[] ans = new ListNode[k];
ListNode index = head;
int size = 0;
while (head != null) {
size++;
head = head.next;
}
int part = size / k;
int extra = size % k;
if (part < 1) {
for (int i = 0; i < k; i++) {
if (index == null) {
ans[i] = null;
} else {
ListNode temp = index;
index = index.next;
temp.next = null;
ans[i] = temp;
}
}
} else {
for (int i = 0; i < k; i++) {
int range = 1;
int partOne = part;
partOne = extra > 0 ? partOne + 1 : partOne;
ListNode temp = index;
while (range < partOne) {
index = index.next;
range++;
}
ListNode t = index;
index = index.next;
t.next = null;
ans[i] = temp;
extra--;
}
}
return ans;
}
}
[面试题 02.06]回文链表
编写一个函数,检查输入的链表是否是回文的。
示例 1:
输入: 1->2
输出: false
解析
这题用翻转链表就是个坑,代码量太大,简单的方法就是用栈。
Code
class Solution {
public boolean isPalindrome(ListNode head) {
Stack stack = new Stack<Integer>();
ListNode cur = head;
while(cur!=null){
stack.push(cur.val);
cur = cur.next;
}
while(head!=null){
if(head.val!=(Integer)stack.pop()){
return false;
}
head = head.next;
}
return true;
}
}
\