leecode 解题总结:234. Palindrome Linked List

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
using namespace std;
/*
问题:
Given a singly linked list, determine if it is a palindrome.

Follow up:
Could you do it in O(n) time and O(1) space?

分析:给定单链表,能否在O(n)时间和O(1)空间确定其是否是回文的。
有点类似于之前的逆置链表,直接可以将第一个和最后一个进行比较,
但是逆置是本质上是头插法+拆分链表,此题仅需要每次获得最后一个结点,然后与
链表头部进行比较。
还有一个方法就是先逆置链表,然后逐一比较。但是原来的链表都不在了。
难道能边逆置边比较
举例:
1 2 3 4 5
初始新结点为空:找到下一个一个结点2, 2->,原来链表:1 ,2->3->4,比较
2->1,接下来找到4与2表,4->5->NULL

leecode解法:https://leetcode.com/problems/palindrome-linked-list/?tab=Solutions
快慢指针,来确定中点,然后逆置后面半段链表,牛逼。
考虑到不能使用额外的空间,则需要使用逆置。
逆置:下一个结点插入到当前结点的头部,典型的头插法。另外空链表算回文应该


输入:
5
1 2 3 2 1
4
1 2 2 1
5
1 3 2 2 1

4
1 2 3 1
2
1 2
2
1 1

1
1
输出:
true
true
false

false
false
true

true

1 2 3 4
slow:1,fast:1,fast:3,slow:2,fats:NULL , slow:3
1 2 3 4 5
slow:1,fast:1,fast:3,slow:2,fast:5,fast->next:NULL ,slow:3
slow结点前面部分逆置
由于slow偏后,将slow及其之后部分逆置即可,然后与头部比较

关键:
1 快慢指针,来确定中点,然后逆置后面半段链表,牛逼。
考虑到不能使用额外的空间,则需要使用逆置。
逆置:下一个结点插入到当前结点的头部,典型的头插法。另外空链表算回文应该
2 由于slow偏后,将slow及其之后部分逆置即可,然后与头部比较
*/

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(!head || NULL == head->next)
		{
			return true;
		}
		ListNode* slow = head;
		ListNode* fast = head;
		ListNode* previous = NULL;
		while(fast && fast->next)
		{
			previous = slow;
			slow = slow->next;
			fast = fast->next->next;
		}
		//将后面半段逆置
		ListNode* newHead = reverseList(slow);
		ListNode* newNode = newHead;
		ListNode* node = head;
		bool isPal = true;
		while(newNode && node)
		{
			if(newNode->val != node->val)
			{
				isPal = false;
				break;
			}
			newNode = newNode->next;
			node = node->next;
		}
		//再次逆置,将链表恢复原状
		newHead = reverseList(newHead);
		if(previous)
		{
			previous->next = newHead;
		}
		return isPal;
    }

	ListNode* reverseList(ListNode* head)
	{
		if(!head || NULL == head->next)
		{
			return head;
		}
		ListNode* next = NULL;
		ListNode* newHead = NULL;
		//头插法来逆置
		while(head)
		{
			next = head->next;
			head->next = newHead;
			newHead = head;
			head = next;
		}
		return newHead;
	}
};

void print(ListNode* head)
{
	if(!head)
	{
		cout << "no result" << endl;
	}
	ListNode* tempHead = head;
	while(head)
	{
		cout << head->val << " ";
		head = head->next;
	}
	cout << endl;
	head = tempHead;
}

ListNode* buildList(vector<int>& nums)
{
	if(nums.empty())
	{
		return NULL;
	}
	int size = nums.size();
	ListNode* head ;
	ListNode *tail;
	ListNode* node;
	for(int i = 0 ; i < size ; i++)
	{
		if(i)
		{
			node = new ListNode(nums.at(i));
			tail->next = node;
			tail = node;
		}
		else
		{
			head = new ListNode(nums.at(i));
			tail = head;
		}
	}
	return head;
}

void deleteList(ListNode* head)
{
	ListNode* node;
	while(head)
	{
		node = head->next;
		delete head;
		head = node;
	}
}

void process()
{
	 vector<int> nums;
	 int value;
	 int num;
	 Solution solution;
	 vector<int> result;
	 while(cin >> num )
	 {
		 nums.clear();
		 for(int i = 0 ; i < num ; i++)
		 {
			 cin >> value;
			 nums.push_back(value);
		 }
		 ListNode* head = buildList(nums);
		 bool answer = solution.isPalindrome(head);
		 if(answer)
		 {
			 cout << "true" << endl;
		 }
		 else
		 {
			 cout << "false" << endl;
		 }
		 print(head);
		 deleteList(head);//删除节点了
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值