《编程之法》1.5回文判断

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qibofang/article/details/51924834

题目描述:给定一个字符串,判断该字符串是否为回文字符串,是则返回true,否则返回false。所谓回文串是指字符串从前往后读,以及从后往前读,结果一致,如:madam, 12344321等

解法1:从两头往中间扫,定义两个指针,分别指向字符串的头和尾,并分别向前和向后移动,依次判断对应元素是否都相同。时间复杂度为O(n),空间复杂度为O(1)。

#include <iostream>
#include <string>
using namespace std;
bool IsPalindrome(string &str){
	int len = str.size();
	if(len == 0)
		return false; //空串返回false
	int start = 0, end = str.size()-1;
	while(start < end){
		if(str[start] != str[end])
			return false;
		++start;
		--end;
	}
	return true;
}

int main(){
	string str;
	while(cin >> str){
		if(IsPalindrome(str))
			cout << "true\n";
		else
			cout << "false\n";
	}
	return 0;
}
解法2:从中间往两头扫,定义两个指针,先判断字符串字符个数,奇数则将两个指针指向字符串正中间那个元素,偶数则将两个指针指向字符串正中间的那两个元素,然后相背移动,依次比较对应元素看是否都相等(可以随便以一个字符串比划一下,应该能够包含所有的情况)。时间复杂度为O(n),空间复杂度为O(1)。

#include <iostream>
#include <string>
using namespace std;
bool IsPalindrome(string &str){
	int len = str.size();
	if(len == 0)
		return false; //空串返回false
	int left, right;
	if(len % 2 == 1){ //根据字符串中字符的个数来对两个指针进行初始化定位
		left = len / 2; right = len / 2;
	}
	else{
		left = len / 2 - 1; right = len / 2;
	}
	while(left >= 0){
		if(str[left] != str[right])
			return false;
		--left;
		++right;
	}
	return true;
}

int main(){
	string str;
	while(cin >> str){
		if(IsPalindrome(str))
			cout << "true\n";
		else
			cout << "false\n";
	}
	return 0;
}


举一反三:
链表回文:判断一条单向链表是不是回文
解法:先输入一个字符串,将其构成单链表。之后,可先定位到链表的中间位置,再将链表的后半段逆置。之后使用两个指针同时从链表头部和中间开始逐一向后遍历比较。时间复杂度为O(n),空间复杂度为O(1)。
单链表尾插法或翻转的图示如下:


#include <iostream>
#include <string>
using namespace std;
struct Node{
	char data;
	Node *next;
};

Node * CreateList(string &str){
	Node *tmp, *head = NULL;
	if(str.size() == 0)
		return head;
	//字符串长为0则直接返回,否则先构建一个node,再组建整个链表
	head = (Node *)malloc(sizeof(Node));
	head->data = str[0];
	int i;
	Node *p = head;
	for(i = 1; i < str.size(); ++i){
		tmp = (Node *)malloc(sizeof(Node));
		tmp->data = str[i];
		p->next = tmp;//p连接到tmp
		p = p->next;//p移动到下个位置
	}
	p->next = NULL;
	return head;
}
bool ReverseListRight(Node *head, int len){
	int mid, i = 0;
	if(len % 2 == 1) mid = len / 2;
	else mid = len / 2 - 1; //由于需要逆转后半段,故需要定位到整个后半段的前一个位置
	Node *left = head, *right = head;
	while(i++ < mid)
		right = right->next;
	//开始翻转后半段
	Node *p = right->next, *q;
	right->next = NULL;
	while(p){//不断插入p
		q = p->next;//用q保存p所指下一结点并最后赋给p
		p->next = right->next;
		right->next = p;
		p = q;
	}
	//while(head){ //用来测试是否正确翻转正确
	//	cout << head->data;
	//	head = head->next;
	//}
	//cout << endl
	//回文串判断
	bool tag = true;
	right = right->next;
	while(right){
		if(right->data != left->data)
			tag = false;
		right = right->next;
		left = left->next;
	}
	if(tag)
		return true;
	else
		return false;
}
int main(){
	string str;
	while(cin >> str){
		Node *head = CreateList(str);
		if(ReverseListRight(head, str.size()))
			cout << "true\n";
		else
			cout << "false\n";
	}
	return 0;
}
栈回文:判断一个栈是不是回文
解法:将一个字符串入栈后出栈,并得到了原字符串的逆置字符串,依次比较原字符串与逆置字符串的对应下标中的数值是否相等,即原字符串:12345,出栈得到的逆置字符串:54321,故不相等。而字符串12321得到的逆置字符串12321与其相等,时间复杂度为O(n),空间复杂度为O(n)。
#include <iostream>
#include <string>
#include <stack>
using namespace std;
stack<char> sta;
bool IsPalindrome(string &str, string &ans){
	int i;
	for(i = 0; i < str.size(); i++)
		sta.push(str[i]);
	for(i = 0; i < str.size(); i++){
		ans[i] = sta.top();
		sta.pop();
	}
	for(i = 0; i < str.size(); i++)
		if(ans[i] != str[i])
			return false;
	return true;
}

int main(){
	string str, ans;
	while(cin >> str){
		ans = str; //需要对ans初始化,否则显示超出下标范围
		if(IsPalindrome(str, ans))
			cout << "true\n";
		else
			cout << "false\n";
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qibofang/article/details/51924834