两数相加
Question:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
Solution:
这道题本身很简单,想复习一下c语言,所以用c来做了:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode* head=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* tail=head;
int count=0,sum=0;
for(;l1&&l2;l1=l1->next,l2=l2->next){
sum=l1->val+l2->val+count;
if(sum>9){
sum-=10;
count=1;
}
else
count=0;
tail->next=(struct ListNode*)malloc(sizeof(struct ListNode));
tail=tail->next;
tail->val=sum;
}
l1 = l1?l1:l2;
for(;l1;l1=l1->next){
sum=l1->val+count;
if(sum>9){
sum-=10;
count=1;
}
else
count=0;
tail->next=(struct ListNode*)malloc(sizeof(struct ListNode));
tail=tail->next;
tail->val=sum;
}
if(count){
tail->next=(struct ListNode*)malloc(sizeof(struct ListNode));
tail=tail->next;
tail->val=count;
}
tail->next=NULL;
tail=head;
head=head->next;
free(tail);
return head;
}
奇偶链表
Question:
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例 2:
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
说明:
应当保持奇数节点和偶数节点的相对顺序。
链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。
Solution:
将链表中所有节点指向它的下下个节点,然后将奇数链表的尾节点连在偶数链表的头结点上:
ListNode* oddEvenList(ListNode* head) {
if(NULL == head || NULL == head->next || NULL == head->next->next) return head;
ListNode* p=head, *temp=head, *secHead=head->next, *pre=nullptr;
int count = 0;
while(p){
count++;
if(NULL == p->next) break;
temp = p->next;
p->next = p->next->next;
pre = p;
p = temp;
}
if(count % 2 == 0)
pre->next = secHead;
else
p->next = secHead;
return head;
}
其中,pre用来记录当链表结点数为偶数时,最后一个奇数节点的位置。
这道题我是看的网上的思路,本来自己写的,但是写了半天弄的很乱,思路是一个指向奇数节点,一个指向偶数节点,每次把偶数节点后面的奇数节点提前到奇数节点后。
ListNode* oddEvenList(ListNode* head) {
if (!head || !head->next) return head;
ListNode *pre = head, *cur = head->next;
while (cur && cur->next) {
ListNode *tmp = pre->next;
pre->next = cur->next;
cur->next = cur->next->next;
pre->next->next = tmp;
cur = cur->next;
pre = pre->next;
}
return head;
}
不得不说链表指来指去的还是很容易弄迷的,一定要多练。
相交链表
Question:
编写一个程序,找到两个单链表相交的起始节点。
注意:
如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
Solution:
先把两个链表右对齐,然后遍历比较即可。
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA || !headB) return NULL;
ListNode *a = headA, *b = headB;
int len = 0;
while(a != NULL && b != NULL)
{
a = a -> next;
b = b -> next;
}
if(a == NULL)
{
while(b != NULL)
{
headB = headB -> next;
b = b -> next;
}
}
if(b == NULL)
{
while(a != NULL)
{
headA = headA -> next;
a = a -> next;
}
}
while(headA)
{
if(headB == headA) return headB;
headA = headA -> next;
headB = headB -> next;
}
return NULL;
}