LeetCode-鏈表相關面試題(二)

一,刪除排序鏈表中的重複元素(83題)

題目要求:給定一個排序鏈表,刪除所有重複的元素,使得每個元素只出現一次。

     

解題思路:1,首先判斷鏈表是否爲空,如果爲空,返回空

2,是否只有一個元素,如果只有一個元素,返回head

3,循環遍歷鏈表,刪除值和它之前結點相等的結點,注意,將每一個結點都和它之前的結點進行比較

代碼實現:

struct ListNode* deleteDuplicates(struct ListNode* head){
    if(head == NULL || head->next == NULL) {
        return head;
    }
    //如果鏈表爲空,返回head
    //如果鏈表只有一個元素,返回head;
    //否則,遍歷循環,刪除後面的元素,接着判斷是否繼續刪除
    struct ListNode* cur = head;
    while(cur->next != NULL) {
        struct ListNode* next = cur->next;
        if(cur->val == cur->next->val) {
            cur->next = cur->next->next;
            free(next);
            continue;
        }
        cur = cur->next;
    }
    return head;
}

二:刪除排序鏈表中的重複元素 II(82題)

題目要求:給定一個排序鏈表,刪除所有含有重複數字的節點,只保留原始鏈表中 沒有重複出現 的數字。

   

解題思路:1,首先判斷鏈表是否爲空
2,申請一個結點node,作爲原鏈表的起始結點,
3,定義三個指針,prev cur next 分別指向node , head , head->next 
4,判斷二三結點值是否相等,
5,如果不相等,所有指針往後挪,繼續判斷,
6,如果相等,第三個指針往後挪,
7,繼續判斷,直到不相等爲止,將prev->next 改爲 next  將cur 改爲next,將next改爲next->next;
8,將cur指向node->next 
9,釋放掉node ,返回cur 
10,注意:此處沒有考慮重複結點的釋放問題

代碼實現

struct ListNode* deleteDuplicates(struct ListNode* head) {
	if (head == NULL || head->next == NULL) {
		return head;
	}
	struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
	node->next = head;
	struct ListNode* prev = node;
	struct ListNode* cur = head;
	struct ListNode* next = head->next;
	while (next != NULL) {
		if (cur->val != next->val) {
			prev = cur;
			cur = next;
			next = next->next;
		}
		else {
			while (next != NULL && next->val == cur->val) {
				next = next->next;
			}
			prev->next = next;
			cur = next;
			if (next != NULL) {
				next = next->next;
			}
		}
	}
	cur = node->next;
	free(node);
	return cur;
}

三:複製帶隨機指針的鏈表(138題)

題目要求

給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。

要求返回這個鏈表的深拷貝

題目解釋:每個結點指針域裏面都有三個值,一個結點的值,一個保存指向下一個結點的指針,一個保存該結點指向隨機結點的指針。

例如:該圖中,1結點的值爲1,next指向2結點,random指向2結點,2結點的值爲2,next指向NULL,random指向自己,

題目要求爲將這樣一個複雜鏈表複製一份,返回的鏈表和原鏈表一樣。

解題思路:1,首先判斷鏈表是否爲空,
2,如果爲空,返回空
3,往每個結點後創建一個新結點,
4,設置新結點的random
5,拆分鏈表,返回新鏈表

代碼實現

class Node {
public:
	int val;
	Node* next;
	Node* random;

	Node() {}

	Node(int _val, Node* _next, Node* _random) {
		val = _val;
		next = _next;
		random = _random;
	}
};
class Solution {
public:
	Node* copyRandomList(Node* head) {
		if (head == NULL) {
			return head;
		}
		Node* cur = head;
		while (cur != NULL) {
			Node* newNode = (Node*)malloc(sizeof(Node));
			newNode->val = cur->val;
			newNode->random = NULL;
			newNode->next = cur->next;
			cur->next = newNode;
			cur = newNode->next;
		}
		cur = head;
		while (cur != NULL) {
			if (cur->random != NULL) {
				cur->next->random = cur->random->next;
			}
			cur = cur->next->next;
		}
		cur = head;
		Node* newHead = head->next;
		while (cur != NULL) {
			Node* newNode = cur->next;
			cur->next = newNode->next;
			if (newNode->next != NULL) {
				newNode->next = newNode->next->next;
			}
			cur = cur->next;
		}
		return newHead;
	}
};

四:刪除鏈表的倒數第N個節點(19題)

題目要求:給定一個鏈表,刪除鏈表的倒數第 個節點,並且返回鏈表的頭結點。

解題思路

1,首先判斷鏈表是否爲空,如果爲空,返回NULL
2,定義快慢指針,fast slow
3,快指針先走n步, 並且不能爲空(fast != NULL &&n > 0)
4,接下來判斷fast可能退出的幾個條件
(1)如果因爲fast == NULL並且n沒有減到0退出,說明,要刪除的結點不符合要求,
將原鏈表返回,return head;
(2)如果因爲fast == NULL 並且n 剛好減到 0 , 說明要刪除的結點爲第一個結點,保存第二個結點的地址
釋放第一個結點的空間,返回第二個結點的地址。
(3)fast先走了n步,然後,slow和fast同時走,直到fast->next == NULL
這時說明slow->next 即爲要刪除的結點,將slow->next結點保存記爲next結點,將slow->next改爲slow->next->next
5,最後一步釋放next結點,返回head

代碼實現

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
	if (head == NULL) {
		return NULL;
	}
	struct ListNode* slow = head;
	struct ListNode* fast = head;
	while (fast != NULL && n > 0) {
		n--;
		fast = fast->next;
	}
	if (fast == NULL && n != 0) {
		return head;
	}
	else if (fast == NULL && n == 0) {
		struct ListNode* next = head->next;
		free(head);
		return next;
	}
	while (fast->next != NULL && slow != NULL) {
		fast = fast->next;
		slow = slow->next;
	}
	struct ListNode* next = slow->next;
	slow->next = slow->next->next;
	free(next);
	return head;
}

五:環形鏈表 II(142題)

題目要求:給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null

     

解題思路:1,給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。
2,首先判斷鏈表是否爲空,如果爲空,返回空
3,定義兩個指針,快慢指針fast slow,
4,快指針每次走兩步,慢指針每次走一步
5,用一個do while循環,一步一步走判斷是否爲空,如果爲空,退出循環,返回空
6,否則直到快慢指針相遇,結束循環,說明鏈表有環,
7,定義兩個指針分別指向head 和 fast 的位置,
8,使用循環找到相遇點,返回該結點。

代碼實現

struct ListNode *detectCycle(struct ListNode *head) {
	if (head == NULL) {
		return NULL;
	}
	struct ListNode *fast = head;
	struct ListNode *slow = head;
	do {
		fast = fast->next;
		if (fast == NULL){ break; }
		fast = fast->next;
		if (fast == NULL){ break; }
		slow = slow->next;
	} while (slow != fast);
	if (fast == NULL) {
		return NULL;
	}
	struct ListNode *p1 = head;
	struct ListNode *p2 = fast;
	while (p1 != p2) {
		p1 = p1->next;
		p2 = p2->next;
	}
	return p1;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章