2. Add Two Numbers(Linked List, Math)两数相加
题目描述:
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807
思路分析:
需要申请一个新链表来存放两数之和,申请一个新空间来存放进位。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int tmp = 0;
ListNode list(0), *pre = &list;//将list的地址赋予pre所指向的内存空间
while(l1 || l2 || tmp){
int sum = (l1 ? l1 -> val : 0) + (l2 ? l2 -> val : 0) + tmp;
tmp = sum / 10;
pre -> next = new ListNode(sum % 10);//需要在pre后面增加新节点,并赋值
pre = pre -> next; //指针后移,指向新节点
l1 = l1 ? l1 -> next : l1;
l2 = l2 ? l2 -> next : l2;
}
return list.next;
}
};
19. Remove Nth Node From End of List(Linked List)删除链表的倒数第N个节点
题目描述:
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
思路分析:
首先保证n有效,考虑两种特殊情况。1. 提前判读一下是否为0,若为0直接返回head。然后要统计节点数 2. n 是否为列表节点总数,若是,则单独处理。接下来找到待删除节点的前驱,由于所给列表没有头结点,所以要特殊处理一下。接下来正常删除节点即可。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(n == 0) return head;
ListNode* cur = head; int sum = 0;
while(cur){// count the node number
cur = cur -> next; ++sum;
}
if(sum == n){// remove first node
ListNode* ret = head -> next; delete head; return ret;
}
int x = sum - n - 1;//因为所给的列表没有头结点,head直接指向第一个节点
cur = head;
while(x){//找到待删节点的前驱
cur = cur -> next; --x;
}
ListNode* rem = cur -> next;
cur -> next = rem -> next;
delete rem;
return head;
}
};
21. Merge Two Sorted Lists(Linked List)合并两个有序链表
题目描述:
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4
思路分析:
非递归,效率高。 算法时间复杂度是O(m+n),m和n分别是两条链表的长度,空间复杂度是O(1)
若其中一个链表为空,则直接返回另一个;定义一个新链表,需要至少定义两个节点:1.头结点,用于返回;2.当前节点, 用于对链表元素赋值以及跳转到下一个节点。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1 == NULL) return l2; //返回较长的链表
if(l2 == NULL) return l1;
ListNode* head = new ListNode(-1);//定义头结点,作为静节点,值初始化为-1,不影响后面判断
ListNode* tmp = head; //定义当前节点,作为动节点,并将tmp指向head
while(l1 != NULL && l2 != NULL){
if(l1 -> val <= l2 -> val){
tmp -> next = l1; l1 = l1 -> next;
}
else{
tmp -> next = l2; l2 = l2 -> next;
}
tmp = tmp -> next;
}
if(l1 != NULL) tmp -> next = l1;
if(l2 != NULL) tmp -> next = l2;
return head -> next;
}
};
24. Swap Nodes in Pairs(Linked List)两两交换链表中的节点
题目描述:
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
示例:
给定1->2->3->4
, 你应该返回2->1->4->3
.
说明:
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路分析:
定义一个新链表,一个头结点,一个当前节点。当前节点和当前节点的后继节点都不为空时交换。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* newhead = new ListNode(-1);
newhead -> next = head;
ListNode* preNode = newhead;
ListNode* curNode = head;
while(curNode != NULL && curNode -> next != NULL){
//swap curNode and curNode -> next
preNode -> next = curNode -> next;
curNode -> next = preNode -> next -> next;
preNode -> next ->next = curNode;
// go over two nodes
preNode = curNode;
curNode = curNode -> next;
}
head = newhead -> next;
delete newhead;
return head;
}
};