0928面试小结:删除有序链表中的重复元素

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);

}

附上自己写的打印链表的辅助函数:

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

#ifndef ALGORITHMS_HELPERLIST_H
#define ALGORITHMS_HELPERLIST_H

#include <iostream>
using namespace std;

struct ListNode{
	int val;
	ListNode* next;
	ListNode(int _val):val(_val){
		this->next = NULL;
	};

};

// 递归打印链表
void printList(ListNode* head)
{
	if(head==NULL) return;
	cout<<head->val<<" ";
	printList(head->next);
}

// 反转打印链表
void rprintList(ListNode* head)
{
	if(head==NULL) return;
	rprintList(head->next);
	cout<<head->val<<" ";
}



#endif //ALGORITHMS_HELPERLIST_H

此题为leetcode No.83原题,中等难度。当场没做出来,只能证明我菜。
输了说什么都像是借口,好好学习吧还是。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值