0928面試小節:刪除有序連結串列中的重複元素

wbzhang233發表於2020-09-28

0928美團面試真題。
幾天沒做題,真的手生…腦子確實很緊張,有點兒轉不動。最後當場掛麵了,面對現實,平靜接受吧。
事後遭遇YZT嘲諷,哈哈哈,倒也沒什麼,繼續加油就完事了…能走到哪一步就算哪一步吧!?

刪除有序連結串列中重複出現的節點


如輸入:1,2,3,3,4,4,5
則輸出:1,2,5


現在腦子清醒點了,面試中:
第一步應該是審題,問清楚要求…然後丟擲一兩個可行的解(即使笨拙,但可靠),然後細化一些內容。
第二,先論證解法是否可行,切勿急忙忙敲下程式碼。
第三,將想法付諸程式碼。如果在牛客上寫不出來,除錯不成功,通常不給本地除錯機會。還是得畫圖逐步來分析(切記:以後面試一定要帶上紙和筆,尤其是對於連結串列和dp相關的題,可以畫出來,不然抽象起來…緊張的時候可能會有紕漏。

言歸正傳,此題顯然演算法簡單或者中級題。傻瓜式的可選的方案有:

  1. 雜湊。
    遍歷連結串列…雜湊map統計每一個值出現的次數;將只出現一次的值,存入vector陣列。恢復連結串列(這一步實際上很折騰)。

  2. 常規解法:建議畫圖抽象出來
    分析:
    1)凡事先特判! 先特例,再抽象一般。
    此題中:考慮,頭結點head為空或者head->next為空,則分別返回NULL和head即可。
    2)一般:連結串列多於1個節點
    由於連結串列頭結點可能存在重複,並且連結串列有序,則重複值必然連續…即curr->val !=curr->next->val成立時,curr->val不重複,否則尋找下一個不等於curr->val的節點。
    我們可以使用一個啞巴節點(此題不必須),來記錄不重複的節點。
    curr_num記錄當前節點的值:

  • curr->val !=curr->next->val滿足時,將該節點的值加入連結串列,
  • 否則尋找下一個值不等於curr_num的節點。

直到curr指標遍歷到連結串列末端節點,此時curr->next==NULL

則最後一個節點未新增進去,此時判斷其值是否等於curr_num即可,若不等,則加入。

以下為事後諸葛程式碼,歡迎批評斧正!

//
// Created by wbzhang on 2020/9/28.
//

#include <iostream>
#include <vector>
#include "../00-TopFrequency/helperList.h"
using namespace std;

class Solution {
public:
	ListNode *deleteDuplicates(ListNode *head) {
		if(!head) return NULL;
		if(!head->next) return head; // 特判

		// 啞巴節點
		ListNode *dummyNode = new ListNode(-1);
		ListNode *pre = dummyNode,*curr = head;

		int curr_num = curr->val;
		while(curr!=NULL && curr->next!=NULL)
		{
			curr_num = curr->val;
			if(curr->next->val != curr_num){
				ListNode* newNode =  new ListNode(curr_num);
				pre->next = newNode;
				pre = pre->next;

//				cout<<"once..."<<endl;
//				printList(dummyNode->next);
//				cout<<endl;
			}

			// 尋找下一個不同的值
			while(curr->val == curr_num && curr->next!=NULL){
				curr = curr->next;
			}

		}

		// 最後一個節點無法覆蓋到
		if(curr_num!=curr->val){
			pre->next = curr;
		}

//		cout<<"once..."<<endl;
//		printList(dummyNode->next);
//		cout<<endl;
		return dummyNode->next;
	}
};


int main()
{
	// 自選若干組測試用例如下:
//		vector<int> nums = {1,2,3,3,4,4,5};
	vector<int> nums = {1,2,2,3,3,4,4,5,5,5,5,5,5};
//	vector<int> nums = {};
//	vector<int> nums = {1};

	// 構建連結串列
	ListNode *head;
	if(nums.size()>0){
		head = new ListNode(nums[0] );
		ListNode *curr = head;

		for (int i = 1; i < nums.size(); ++i) {
			ListNode *newNode = new ListNode( nums[i] );
			curr->next = newNode;
			curr = curr->next;
		}

		printList(head);
		cout<<" ---" <<endl;
	}else{
		head = NULL;
	}

	Solution solu;
	ListNode* ans = solu.deleteDuplicates(head);
	cout<<"ans: "<<endl;
	printList(ans);

}

相關文章