2. Add Two Numbers

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

暴力解法:


解题思路:

1.其中一个链表为空的情况;

2.链表长度相同时,且最后一个节点相加有进位的情况;

3.链表长度不等,短链表最后一位有进位的情况,且进位后长链表也有进位的情况;

/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1==null){
return l2;
}
if(l2==null){
return l1;
}
int len1 = getLength(l1);
int len2 = getLength(l2);
ListNode head = null;
ListNode plus = null;
if(len1>=len2){
head = l1;
plus = l2;
}else{
head = l2;
plus = l1;
}
ListNode p = head;
int carry = 0;
int sum = 0;
while(plus!=null){
sum = p.val + plus.val+carry;
carry = sum/10;
p.val = sum%10;
if(p.next==null&&carry!=0){
ListNode node = new ListNode(carry);
p.next = node;
carry = 0;
}
p = p.next;
plus = plus.next;
}
while(p!=null&&carry!=0){
sum = p.val+carry;
carry = sum/10;
p.val = sum%10;
if(p.next==null&&carry!=0){
ListNode node = new ListNode(carry);
p.next = node;
carry=0;
}
p = p.next;
}
return head;
} public int getLength(ListNode l){
if(l==null){
return 0;
}
int len = 0;
while(l!=null){
++len;
l = l.next;
}
return len;
}
}

递归解法:


复杂度

时间O(n) 空间(n) 递归栈空间

思路

从末尾到首位,对每一位对齐相加即可。技巧在于如何处理不同长度的数字,以及进位和最高位的判断。这里对于不同长度的数字,我们通过将较短的数字补0来保证每一位都能相加。递归写法的思路比较直接,即判断该轮递归中两个ListNode是否为null。

  • 全部为null时,返回进位值
  • 有一个为null时,返回不为null的那个ListNode和进位相加的值
  • 都不为null时,返回 两个ListNode和进位相加的值
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return helper(l1,l2,0);
} public ListNode helper(ListNode l1, ListNode l2, int carry){
if(l1==null && l2==null){
return carry == 0? null : new ListNode(carry);
}
if(l1==null && l2!=null){
l1 = new ListNode(0);
}
if(l2==null && l1!=null){
l2 = new ListNode(0);
}
int sum = l1.val + l2.val + carry;
ListNode curr = new ListNode(sum % 10);
curr.next = helper(l1.next, l2.next, sum / 10);
return curr;
}
}

迭代法:


复杂度

时间O(n) 空间(1)

思路

迭代写法相比之下更为晦涩,因为需要处理的分支较多,边界条件的组合比较复杂。过程同样是对齐相加,不足位补0。迭代终止条件是两个ListNode都为null。

注意

  • 迭代方法操作链表的时候要记得手动更新链表的指针到next
  • 迭代方法操作链表时可以使用一个dummy的头指针简化操作
  • 不可以在其中一个链表结束后直接将另一个链表串接至结果中,因为可能产生连锁进位
public class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
if(l1 == null && l2 == null){
return dummyHead;
}
int sum = 0, carry = 0;
ListNode curr = dummyHead;
while(l1!=null || l2!=null){
int num1 = l1 == null? 0 : l1.val;
int num2 = l2 == null? 0 : l2.val;
sum = num1 + num2 + carry;
curr.next = new ListNode(sum % 10);
curr = curr.next;
carry = sum / 10;
l1 = l1 == null? null : l1.next;
l2 = l2 == null? null : l2.next;
}
if(carry!=0){
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
}

21. Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

思路1:1)考虑特殊情况,两个链表至少有一个为空;

     2)考虑两个链表长度不一样的情况;

/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if(l1==null)
return l2;
if(l2==null)
return l1; ListNode head;
if(l1.val<=l2.val){
head = new ListNode(l1.val);
l1 = l1.next;
}else{
head = new ListNode(l2.val);
l2 = l2.next;
}
ListNode node = head;
while(l1!=null&&l2!=null){
if(l1.val<=l2.val){
node.next = l1;
node = node.next;
l1 = l1.next;
}else{
node.next = l2;
node = node.next;
l2 = l2.next;
}
}
if(l1!=null){
node.next = l1;
}
if(l2!=null){
node.next = l2;
}
return head;
}
}

206. Reverse Linked List

Reverse a singly linked list.

思路:1)首先判断头节点是否为空,为空则直接返回;

  2)

public class Solution {
public ListNode reverseList(ListNode head) {
if(head==null)
return null;
ListNode newHead = new ListNode(head.val);
ListNode p = head.next;
while(p!=null){
ListNode node = new ListNode(p.val);
node.next = newHead;
p = p.next;
newHead = node;
} return newHead;
}
}
sort-list

Sort a linked list in O(n log n) time using constant space complexity.

思路:要求时间复杂度为O(nlogn),空间复杂度为O(1);

  1.考虑使用归并排序;

  2.归并排序需要找到中点,考虑使用快慢指针;

  3.归并中排序;

/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
if(head==null||head.next==null)
return head;
ListNode mid = getMid(head);
ListNode right = sortList(mid.next);
mid.next = null;
ListNode left = sortList(head);
return mergeList(left,right);
}
public ListNode getMid(ListNode head){
ListNode slow = head;
ListNode fast = head.next;
while(fast!=null&&fast.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
} public ListNode mergeList(ListNode left,ListNode right){
if(left==null)
return right;
if(right==null)
return left;
ListNode head = null;
if(left.val<=right.val){
head = left;
left = left.next;
}else{
head = right;
right = right.next;
}
ListNode node = head;
while(left!=null&&right!=null){
if(left.val<=right.val){
node.next = left;
left = left.next;
}else{
node.next = right;
right = right.next;
}
node = node.next;
}
if(left!=null){
node.next = left;
}
if(right!=null){
node.next = right;
}
return head;
}
}
insertion-sort-list

Sort a linked list using insertion sort.

使用插入的方式对链表进行排序:

插入排序的思路如下:当前数与其前面的有序数依次进行比较,找到适当的位置插入,以此类推,得到最终结果;

此题的思路是:

  1)如果head为空或者head.next为空,则直接返回head;

  2)使用一个节点cur遍历当前待排序的节点,利用另一个节点pre从头开始遍历,若pre的值<=cur的值且两者不同,pre=pre.next;否则,记录第一个>cur的节点及其值,再遍历此节点到cur节点,调整节点值得位置,将cur的值交换到第一个>cur的节点处,直到链表遍历完;

/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode insertionSortList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode cur = head;
while(cur!=null){
ListNode pre = head;
while(pre.val<=cur.val&&pre!=cur){
pre = pre.next;
}
int firstVal = pre.val;
ListNode mark = pre;
while(pre!=cur){
int nextVal = pre.next.val;
int tmp = nextVal;
pre.next.val = firstVal;
firstVal = tmp;
pre = pre.next;
}
mark.val = firstVal;
cur = cur.next;
}
return head;
}
}
 
reorder-list
Given a singly linked list LL0→L1→…→Ln-1→Ln,

reorder it to: L0→LnL1→Ln-1→L2→Ln-2→…

You must do this in-place without altering the nodes' values.

For example,
Given{1,2,3,4}, reorder it to{1,4,2,3}.

解题思路:

  先使用快慢指针找到链表的中点,反转后半部分的链表,再以中点为断点进行前后两部分交叉合并;

/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public void reorderList(ListNode head) {
if(head==null||head.next==null)
return;
ListNode fast = head.next;
ListNode slow = head;
while(fast!=null&&fast.next!=null){
slow = slow.next;
fast = fast.next.next;
}
ListNode pre = reverseList(slow.next);
slow.next = pre;
ListNode p = head;
ListNode q = slow.next;
while(q!=null&&p!=null){
slow.next = q.next;
q.next = p.next;
p.next = q;
p = q.next;
q = slow.next;
}
}
  //反转单链表
public ListNode reverseList(ListNode head){
if(head==null||head.next==null)
return head;
ListNode cur = head.next;
ListNode pre = head;
while(cur!=null){
ListNode node = cur.next;
cur.next = pre;
pre = cur;
cur = node;
}
head.next = cur;
return pre;
}
}

LeetCode之链表的更多相关文章

  1. Leetcode解题-链表(2.2.0)基础类

    1 基类的作用 在开始练习LeetCode链表部分的习题之前,首先创建好一个Solution基类,其作用就是: Ø  规定好每个子Solution都要实现纯虚函数test做测试: Ø  提供了List ...

  2. LeetCode 单链表专题 (一)

    目录 LeetCode 单链表专题 <c++> \([2]\) Add Two Numbers \([92]\) Reverse Linked List II \([86]\) Parti ...

  3. 【算法题 14 LeetCode 147 链表的插入排序】

    算法题 14 LeetCode 147 链表的插入排序: 解题代码: # Definition for singly-linked list. # class ListNode(object): # ...

  4. 关于leetcode中链表中两数据相加的程序说明

    * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ ...

  5. LeetCode之“链表”:Reverse Linked List && Reverse Linked List II

    1. Reverse Linked List 题目链接 题目要求: Reverse a singly linked list. Hint: A linked list can be reversed ...

  6. 关于LeetCode上链表题目的一些trick

    最近在刷leetcode上关于链表的一些高频题,在写代码的过程中总结了链表的一些解题技巧和常见题型. 结点的删除 指定链表中的某个结点,将其从链表中删除. 由于在链表中删除某个结点需要找到该结点的前一 ...

  7. Leetcode中单链表题总结

    以下是个人对所做过的LeetCode题中有关链表类型题的总结,博主小白啊,若有错误的地方,请留言指出,谢谢. 一.有关反转链表 反转链表是在单链表题中占很大的比例,有时候,会以各种形式出现在题中,是比 ...

  8. LeetCode之链表总结

    链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度.作为一种常用的数据结构,链表内置在很多高级编程语言里面.既比数组复杂又比树简单,所以链表经常被面试官 ...

  9. leetcode 876. 链表的中间结点 签到

    题目: 给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5] 输出:此列表中的结点 3 (序列化形式: ...

  10. leetcode 反转链表部分节点

    反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m = 2, ...

随机推荐

  1. SGU 140. Integer Sequences 线性同余,数论 难度:2

    140. Integer Sequences time limit per test: 0.25 sec. memory limit per test: 4096 KB A sequence A is ...

  2. plsql的快速生成sql语句设置

    单 单击tool(工具)->的preferences(首选项)  ,进入到首选项页面 在点击user interface 的editor下的autoreplace 的edit按钮        ...

  3. SOA实践指南-读书笔记

    SOA是英文Service-Oriented Architecture,即面向服务架构的缩写. SOA是一种范式,目的是增强灵活性.SOA很适宜处理复杂的分布式系统. SOA方法接受异质(不同的平台, ...

  4. AS中几个较好的插件

    Android ButterKnife Zelezny   自动生成依赖注入代码 Android Parcelable code generator  自动生成Parcelable代码 Selecto ...

  5. CSS元素、边框、背景、列表样式

    一.元素样式 1.width控制元素宽度 2.height控制元素宽度 3.padding控制元素内边距 内容与边框之间的距离 4.margin控制元素外边距 元素边框与其他元素边框之间的距离,如果两 ...

  6. 新手,Visual Studio 2013 配置Boost库,如何编译和选择

    QuantLib installation in VC++ 2010 and later 参考:http://quantlib.org/install/vc10.shtml 1,到官网下载最新的boo ...

  7. 【转】 python 删除非空文件夹

    转自:https://blog.csdn.net/xiaodongxiexie/article/details/77155864 一般删除文件时使用os库,然后利用os.remove(path)即可完 ...

  8. ios开发之-windows下面虚拟机运行osx,以及xcode

    下载vmware osx镜像 https://kickass.to/os-x-mavericks-10-9-retail-vmware-image-t7981468.html (还有个链接下载不了ht ...

  9. 【monkeyrunner】monkeyrunner 实例

    import time import os import re from com.android.monkeyrunner import MonkeyRunner as mr from com.and ...

  10. 刷新SQL Server所有视图、函数、存储过程 更多 sql 此脚本用于在删除或添加字段时刷新相关视图,并检查视图、函数、存储过程有效性。 [SQL]代码 --视图、存储过程、函数名称 DECLARE @NAME NVARCHAR(255); --局部游标 DECLARE @CUR CURSOR --自动修改未上状态为旷课 SET @CUR=CURSOR SCROLL DYNAMIC FO

    刷新SQL Server所有视图.函数.存储过程 更多   sql   此脚本用于在删除或添加字段时刷新相关视图,并检查视图.函数.存储过程有效性. [SQL]代码 --视图.存储过程.函数名称 DE ...