链表题目小结

1. 求单链表中节点的个数

2. 将单链表反转

3. 查找单链表中的倒数第K个节点(k > 0)

4. 查找单链表的中间节点

5. 从尾到头打印单链表

6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序

7. 判断一个单链表中是否有环

8. 判断两个单链表是否相交

9. 求两个单链表相交的第一个节点

10. 已知一个单链表中存在环,求进入环中的第一个节点

11. 删除单向链表中间的某个节点,假定你只能访问该节点

12. 检查链表是否为回文

13. 移除未排序链表中的重复节点

14. 给定两个用链表表示的整数,每个节点包含一个数位,这些数位是方向存放的,对这两个整数求和,并用链表形式返回结果


链表节点定义:

typedef struct ListNode {
	int value;
	struct ListNode *next;
}ListNode;

1. 求单链表中结点的个数

int getListLength(ListNode *head) {
	if (head == NULL)
		return 0;
		
	ListNode *p = head;
	int count = 0;
	
	while (p) {
		count++;
		p = p->next;
	}
	
	return count;
}

2. 将单链表反转

ListNode* reverseList(ListNode *head) {
	if (head == NULL)
		return head;
		
	ListNode *rHead = NULL;
	ListNode *p = head;
	
	while (p) {
		ListNode *t = p;
		p = p->next;
		t->next = rHead;
		rHead = t;
	}
	
	return rHead;
}

3. 查找单链表中的倒数第K个结点(k > 0)

ListNode* getKthNodeFromEnd(ListNode *head, int k)
{
	if (head == NULL || k <= 0)
		return head;

	ListNode *slow = head;
	ListNode *fast = head;
	while (k > 0 && fast != NULL) {
		fast = fast->next;
		k--;
	}
	
	if (k > 0)
		return NULL;
		
	if (fast == NULL) {
		return slow;
	}
	
	while (fast->next) {
		slow = slow->next;
		fast = fast->next;
	}
	
	return slow->next;
}


4. 查找单链表的中间结点

ListNode* getMidNode(ListNode *head) {
	ListNode *slow = head;
	ListNode *fast = head;
	
	while (fast && fast->next) {
		fast = fast->next->next;
		slow = slow->next;
	}
	
	return slow;
}

5. 从尾到头打印单链表

void reversePlayList(ListNode *head) {
	if (head == NULL)
		return;
		
	PrintListFromEnd(head->next);
	printf("%d ", head->value);
}

6. 已知两个单链表head1和head2各自有序,把它们合并成一个链表依然有序

ListNode* mergeLists(ListNode *head1, ListNode *head2) {
	ListNode *head = NULL;
	ListNode *p = NULL;
	ListNode *t;
	
	while (head1 && head2) {
		if (head1->value < head2->value) {
                        if (head == NULL) {
				head = p = head1;
			}
			
			t = head1;
			head1 = head1->next;
		} else {
			if (head == NULL) {
				head = p = head2;
			}
		
			t = head2;
			head2 = head2->next;
		}
		
		p->next = t;
		p = t;
	}
	
	if (head1 == NULL)
		p->next = head2;
	
	if (head2 == NULL)
		p->next = head1;
	
	return head;
}



7. 判断一个单链表中是否有环

bool hasCircle(ListNode *head) {
	ListNode *slow = head;
	ListNode *fast = head;
	
	while (fast && fast->next) {
		fast = fast->next->next;
		slow = slow->next;
		if (fast == slow) //有环快慢指针必相遇
			return true;
	}
	
	return false;
}

8. 判断两个单链表是否相交

bool isIntersect(ListNode *head1, ListNode *head2) {
	if (head1 == NULL || head2 == NULL)
		return false;
	
	while (head1->next)
		head1 = head1->next;
	
	while (head2->next)
		head2 = head2->next;
	
	return head1 == head2; //若相交,最后一个节点必为两者所有
}

9. 求两个单链表相交的第一个节点

ListNode* getFirstCommonNode(ListNode *head1, ListNode *head2) {
	if (head1 == NULL || head2 == NULL)
		return NULL;
	
	int len1 = 0, len2 = 0;
	ListNode *p1 = head1;
	ListNode *p2 = head2;
	
	while (p1) {
		len1++;
		p1 = p1->next;
	} 
	
	while (p2) {
		len2++;
		p2 = p2->next;
	}
	
	if (p1 != p2)
		return NULL;
	
	p1 = head1;
	p2 = head2;
	
	if (len1 > len2) {
		int k = len1 - len2;
		while (k--)
			p1 = p1->next;
	} else {
		int k = len2 - len1;
		while (k--)
			p2 = p2->next;
	}
	
	while (p1 != p2) {
		p1 = p1->next;
		p2 = p2->next;
	}
	
	return p1;
}

10. 已知一个单链表中存在环,求进入环中的第一个节点

从环中相遇的节点,把链表分开,转成求两链表的相交的第一个节点

ListNode* getFirstNodeInCircle(ListNode *head) {
	if (head == NULL || head->next == NULL)
		return NULL;
		
	ListNode *fast = head;
	ListNode *slow = head;
	
	while (fast->next->next) {
		fast = fast->next->next;
		slow = slow->next;
		if (fast == slow)
			break;
	}
	
	if (fast != slow)
		return NULL;
		
	ListNode *p1 = head;
	ListNode *p2 = fast->next;
	int len1 = 1;
	int len2 = 1;
	
	while (p1 != slow) {
		p1 = p1->next;
		len1++;
	}
	
	while (p2 != slow) {
		p2 = p2->next;
		len2++;
	}
	
	p1 = head;
	p2 = fast->next;
	
	if (len1 > len2) {
		int k = len1 - len2;
		while (k--)
			p1 = p1->next;
	} else {
		int k = len2 - len1;
		while (k--)
			p2 = p2->next;		
	}
	
	while(p1 != p2) {
		p1 = p1->next;
		p2 = p2->next;
	}
	
	return p1;
}

11. 删除单向链表中间的某个节点,假定你只能访问该节点

用下一个节点覆盖该节点,当该节点为尾节点时,无法操作

bool deleteNode(ListNode *node) {
	if (node == NULL || node->next == NULL)
		return false;
	ListNode *p = node->next;
	node->value = p->value;
	node->next = p->next;
	delete p;
	return true;
}

12. 检查链表是否为回文

反转链表,然后和原链表比较


13. 移除未排序链表中的重复节点

void deleteDups(ListNode *head) {
	if (head == NULL || head->next == NULL)
		return;
	
	map<int, ListNode *> listMap;
	ListNode *p = head;
	ListNode *temp;
	listMap[p->value] = p;
	while (p->next) {
		if (listMap.find(p->next->value)) {
			temp = p->next;
			p->next = p->next->next;
			delete temp;
		} else {
			listMap[p->next->value] = p->next;
		}
		p = p->next;
	}
}

14. 给定两个用链表表示的整数,每个节点包含一个数位,这些数位是方向存放的,对这两个整数求和,并用链表形式返回结果

ListNode* addTwoNumbers(ListNode *head1, ListNode *head2) {
	ListNode *header = new ListNode(-1);
	ListNode *result = header;
	int val = 0;
	int extra = 0;
	
	while (head1 || head2) {
		val = (head1 != NULL ? head1->value : 0) + (head2 != NULL ? head2->value : 0) + extra;
		extra = val / 10;
		val %= 10;
		ListNode *node = new ListNode(val);
		node->value = val;
		result->next = node;
		result = result->next;
		
		if (head1) {
			head1 = head1->next;
		}
		
		if (head2) {
			head2 = head2->next;
		}
	}

    if (extra > 0) {
		ListNode *node = new ListNode(extra);
		result->next = node;
	}

	result = header->next;
	delete header;
	return result;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值