1. 回文链表的判断
给定一个链表,判断是否为回文链表,我的思路是利用快慢指针先找到链表的中间节点,然后将中间节点之后的部分反转,再将反转的部分和前半部分比较
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
//如果链表是空或者链表只有一个元素则必然为回文链表
if(!head || !head->next)
return true;
//快慢指针法,寻找链表中心
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
}
//链表元素为奇数个
if(fast){
slow->next = reverseList(slow->next);
slow = slow->next;
}
else{
slow = reverseList(slow);
}
while(slow){
if(slow->val != head->val)
return false;
slow = slow->next;
head = head->next;
}
return true;
}
ListNode* reverseList(ListNode* head){
ListNode* first, *reverse;
first = head;
reverse = NULL;
while(first){
ListNode* second = first->next;
first->next = reverse;
reverse = first;
first = second;
}
return reverse;
}
};
2. 删除链表的倒数第n个节点
思路,同样也是利用两个快慢指针,快指针先走n步,当快指针走到链表末尾时(fast == NULL),慢指针就指向了要删除的那个节点。注意需要一个pre指针保存慢指针的前一个节点
class Solution{
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* slow = head;
ListNode* fast = head;
ListNode* pPre = NULL;
for(int i = 0; i < n; i++){
if(fast == NULL)
return head;
fast = fast->next;
}
while(fast){
pPre = slow;
slow = slow->next;
fast = fast->next;
}
//n == length of linkedlist
if(pPre == NULL){
head = slow->next;
delete slow;
}
else{
pPre->next = slow->next;
delete slow;
}
return head;
}
};
3. 合并两个有序的链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == NULL)
{
return l2;
}
if (l2 == NULL)
{
return l1;
}
ListNode* ip1 = l1;
ListNode* ip2 = l2;
ListNode* newHead = (l1->val < l2->val ? l1 : l2);
if(l1->val < l2->val){
ip1=ip1->next;
}
else{
ip2=ip2->next;
}
ListNode* iHead = newHead;
int i = 1;
while(ip1 && ip2){
iHead->next = (ip1->val < ip2->val ? ip1 : ip2);
if(i == 1){
newHead = iHead; //更新头部
}
if(ip1->val < ip2->val){
ip1=ip1->next;
}
else{
ip2=ip2->next;
}
iHead = iHead->next;
i++;
}
//将剩余部分添加到新的链表
if(ip1){
iHead->next = ip1;
ip1 = ip1->next;
iHead = iHead->next;
}
else{
iHead->next = ip2;
ip2 = ip2->next;
iHead = iHead->next;
}
return newHead;
}
};
4.判断链表是否有环
快慢指针,若快指针能够遇到慢指针,说明链表有环
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head->next;
if(slow== NULL || fast == NULL)
return false;
while(slow != fast){
if(fast == NULL || fast->next == NULL)
return fasle;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
5. 在有序链表中删除重复的元素
因为是有序链表,所以只要比较前后两个节点的值就行了。
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* first = head;
if(head == NULL || head->next == NULL)
return head;
while(first && first->next){
ListNode* next1 = first->next;
if(next1->val == first->val){
first->next = next1->next;
delete next1;
}
else first = first->next;
}
return head;
}
};
6.删除链表元素
题意是说给定一个值,删除链表中所有值为给定值的节点,这个题目的技巧在于给这个链表多加一个头节点,从这个头结点开始遍历查找删除
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* preHead = new ListNode(0);
preHead->next = head;
ListNode* p = preHead;
while(p && p->next){
ListNode* q = p->next;
if(q->val == val){
p->next = q->next;
delete q;
}
else p = p->next;
}
return preHead->next;
}
};
7.链表反转
反转一个链表,这个问题其实不算简单,但是由于网上关于这个问题的解答是在太多了,而且估计很多面试笔试什么的也已经把这个问题问烂了,所以这个问题显得有些俗套了,但还是值得去仔细研究的。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* first = head;
ListNode* reverse = NULL;
while(first){
ListNode* second = first->next;
first->next = reverse;
reverse = first;
first = second;
}
return reverse;
}
};
8.成对交换链表节点
[1,2,3,4]交换后[2,1,4,3]。要求时间为线性,空间为常数,有两种方法,一种就是规规矩矩破坏链表结构交换节点,另一种就是不破坏链表结构,交换元素值
第一种方法
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* prev = head;
ListNode* cur = head->next;
while(true){
int t = prev->val;
prev->val = cur->val;
cur->val = t;
prev = prev->next->next;
if(prev == NULL) break;
cur = cur->next->next;
if(cur == NULL) break;
}
return dummy->next;
}
};
第二种方法:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* prev = head;
ListNode* cur = head->next;
while(true){
int t = prev->val;
prev->val = cur->val;
cur->val = t;
prev = prev->next->next;
if(prev == NULL) break;
cur = cur->next->next;
if(cur == NULL) break;
}
return dummy->next;
}
};