9.回文数
因为放假了,所以变成不想营业的一天…但这才练习的第二天,看看自己的渣渣水平,还是果断打开了leetcode,从此和你相依为命,啊啊啊。
这次的题目是判断一个回文数,首先我先想到的是将整数变成字符串,然后将前后两个字符进行对比。
自己写出来的代码如下
class Solution {
public:
bool isPalindrome(int x) {
if(x<0) return 0;
string str_x=to_string(x);
int n=str_x.length();
int i=0,j=n-1;
while(str_x[i]==str_x[j]){
if(n%2==0&&(i+1==j)){
return 1;
}
if(n%2==1&&(i==j)){
return 1;
}
i++;
j--;
}
return 0;
}
};
执行完后,发现效率并没有很高
寻求这个思路一些别的思路
比如在上道题运用的reverse()函数
class Solution {
public:
bool isPalindrome(int x) {
long rev;
if (x < 0) return false;//排除负数
string str_x = to_string(x);//转换成字符串
std::reverse(str_x.begin(), str_x.end());//进行反转
stringstream out(str_x);
out >> rev;//结果写入rev
return x==rev;//比较得出结果
}
};
代码更加简洁,但执行后发现用时更多,我觉得主要是函数调用或者stringstream建立数据流的过。
再看了看相同的算法没有什么好的了,这时候回去看官方思路,还是用数学的算法解决这个问题
代码如下:
public boolean isPalindrome(int x) {
int y = x;
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
long newNum = 0;
while (x != 0) {
newNum = x % 10 + newNum * 10;
x=x/10;
}
if(y == newNum)
return true;
return false;
}
事实证明,效率确实高。
之后有一道相似的题目,判断链表是不是回文的。
234.回文链表
今天是30号,本想着昨天多写几道题,但后来自己一懒惰,导致昨天写的都没发出去,追悔莫及!!所以只能在今天补上了,今天的目标也是写完这道题,因为还想去学习编译和英语。
话不多说,开始看到这道题的时候我的想法是将链表的前半部放进栈中,再利用数据结构的特性,一一进行比较。
数据结构定义如下:
/**
* Definition for singly-linked list.
* 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==NULL) return true;
int num=0;//存放链表长度
ListNode *p=head;
while(p)//计算链表长度
{
num++;
p=p->next;
}
p=head;
int midnum;
if(num%2==0) midnum=num/2;
if(num%2==1) midnum=num/2+1;
stack<int> stack;
for(int i=0;i<midnum;i++){
stack.push(p->val);
p=p->next;
}
if(num%2==1) stack.pop();
while(p&&!stack.empty()){
if(p->val!=stack.top()){
return false;
}
p=p->next;
stack.pop();
}
return true;
}
};
执行之后非常惨烈:
这里需要注意的一个是如何获取链表的中点位置。
方法(1)最小白的办法,遍历链表,获取链表长度,然后分奇数偶数,算出中点在哪。
int num=0;//存放链表长度
ListNode *p=head;
while(p)//计算链表长度
{
num++;
p=p->next;
}
int midnum=num/2;
方法(2)是我看到别人的代码大都这样写,用快慢指针进行实现。至今还没搞懂原理是什么,据说是因为fast指针始终是slow指针的二倍,而且这种方法不用考虑奇数偶数。
//确定中点
while(fast && fast->next){
fast = fast->next->next;
mid = slow;
slow = slow->next;
}
完整的代码借鉴一下别人的思路,发现大家的思路都是把前半部分或者后半部分进行翻转,然后再比较,就比如这个
class Solution{
public:
bool isPalindrome(struct ListNode* head){
if(head == NULL || head->next == NULL) return true;
struct ListNode* fast = head;
struct ListNode* slow = head;
struct ListNode* mid = head;
//确定中点
while(fast && fast->next){
fast = fast->next->next;
mid = slow;
slow = slow->next;
}
mid->next = NULL;
//反转后半部分列表
struct ListNode* pNode, *pNext;
pNode = slow->next;
slow->next = NULL;
pNext = NULL;
while(pNode){
pNext = pNode->next;
pNode->next = slow;
slow = pNode;
pNode = pNext;
}
//判断链表是否相等
while(head){
if(head->val != slow->val) return false;
head = head->next;
slow = slow->next;
}
return true;
}
};
和我的想法不同的是他不用栈实现对比,用两个链表实现相互比较,且指针翻转的时候也直接用链表头插法进行操作。
运行时间大大缩短,但运行空间上并不优秀,当然也算是一些进步==。