牛客题解 | 判断是否为回文字符串

题目## 题目

题目链接

题目的主要信息:
  • 判断字符串是否是回文字符
  • 回文字符即首尾相互往中靠,字符都是相同的
举一反三:

学习完本题的思路你可以解决如下题目:

BM13. 判断一个链表是否为回文结构

BM87. 合并两个有序数组

BM91. 反转字符串

方法一:首尾依次比较法(推荐使用)

知识点:双指针

双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。

思路:

回文字符串正向遍历与逆向遍历结果都是一样的,因此我们可以准备两个对撞指针,一个正向遍历,一个逆向遍历。

//首指针
int left = 0; 
//尾指针
int right = str.length() - 1;
//首尾往中间靠  
while(left < right){  
    ......
}

具体做法:

  • step 1:准备两个指针,一个在字符串首,一个在字符串尾。
  • step 2:在首的指针往后走,在尾的指针往前走,依次比较路过的两个字符是否相等,若是不相等则直接就不是回文。
  • step 3:直到两指针在中间相遇,都还一致就是回文。因为首指针到了后半部分,走过的正好是尾指针走过的路,二者只是交换了位置,比较相等还是一样的。

图示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Java代码实现:

import java.util.*;
public class Solution {
    public boolean judge (String str) {
        //首指针
        int left = 0; 
        //尾指针
        int right = str.length() - 1;
        //首尾往中间靠  
        while(left < right){  
            //比较前后是否相同
            if(str.charAt(left) != str.charAt(right)) 
                return false;
            left++;
            right--;
        }
        return true;
    }
}

C++代码实现:

class Solution {
public:
    bool judge(string str) {
        //首指针
        int left = 0; 
        //尾指针
        int right = str.length() - 1;  
        //首尾往中间靠
        while(left < right){
            //比较前后是否相同 
            if(str[left] != str[right]) 
                return false;
            left++;
            right--;
        }
        return true;
    }
};

Python实现代码:

class Solution:
    def judge(self , str: str) -> bool:
        #首指针
        left = 0 
        #尾指针
        right = len(str) - 1 
        #首尾往中间靠
        while left < right :
            #比较前后是否相同
            if str[left] != str[right] :
                return False
            left += 1
            right -= 1
        return True

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n为字符串长度,最多遍历半个字符串
  • 空间复杂度: O ( 1 ) O(1) O(1),除了常数个临时变量,无额外辅助空间
方法二:反转字符串比较法(扩展思路)

思路:

既然字符串正向遍历与逆向遍历遇到字符都相等,那我们就反转字符串,看看它到底是不是正逆都一样,因为字符串支持整体比较,因此我们可以比较反转后的字符串与原串是不是相等。

具体做法:

  • step 1:使用reverse函数将字符串反转。
  • step 2:比较反转后的字符串,还是与原来的字符串相等,则是回文字符串。

Java代码实现:

import java.util.*;
public class Solution {
    public boolean judge (String str) {
        StringBuffer temp = new StringBuffer(str);
        //反转字符串
        String s = temp.reverse().toString();
        //比较字符串是否相等
        if(s.equals(str))
            return true;
        return false;
    }
}

C++代码实现:

class Solution {
public:
    bool judge(string str) {
        string temp = str;
        //反转字符串
        reverse(str.begin(), str.end()); 
        //比较字符串是否相等
        if(temp == str)
            return true;
        return false;
    }
};

Python实现代码:

class Solution:
    def judge(self , str: str) -> bool:
        temp = str
        #反转字符串
        str = str[::-1] 
        #比较字符串是否相等
        if temp == str:
            return True
        return False

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),反转字符串和比较字符串都是 O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n),辅助字符串temp记录原来的字符串

题目链接

#题解
这是一篇针对初学者的题解,用两种方法解决。
知识点:树,递归
难度:一星

#题解

##方法一:自顶向下
判断一个数是否为平衡二叉树。平衡二叉树是左子树的高度与右子树的高度差的绝对值小于等于1,同样左子树是平衡二叉树,右子树为平衡二叉树。

根据定义,如果我们能够求出以每个结点为根的树的高度,然后再根据左右子树高度差绝对值小于等于1,,就可以判断以每个结点为根的树是否满足定义。
我们可以用hash<treenode*, int>来存以每个结点的树的高度。
代码如下:

map<treenode*, int> hs;
int depth(TreeNode *root) {
    if (!root) return 0;
    if (hs.find(root) != hs.end()) return hs[root];
    int ldep = depth(root-&gt;left);
    int rdep = depth(root-&gt;right);
    return hs[root] = max(ldep, rdep) + 1;
}

然后再用先序遍历:根节点、左子树、右子树来判断以每个结点为根的树是否满足条件。
代码如下:

bool judge(TreeNode *root) {
    if (!root) return true;
    return abs(hs[root-&gt;left] - hs[root-&gt;right]) &lt;= 1 &amp;&amp; 
    judge(root-&gt;left) &amp;&amp; judge(root-&gt;right);
}

最后的代码为:

class Solution {
public:
    map<treenode*, int> hs;
    int depth(TreeNode *root) {
        if (!root) return 0;
        if (hs.find(root) != hs.end()) return hs[root];
        int ldep = depth(root-&gt;left);
        int rdep = depth(root-&gt;right);
        return hs[root] = max(ldep, rdep) + 1;
    }
    bool judge(TreeNode *root) {
        if (!root) return true;
        return abs(hs[root-&gt;left] - hs[root-&gt;right]) &lt;= 1 &amp;&amp; 
        judge(root-&gt;left) &amp;&amp; judge(root-&gt;right);
    }
    bool IsBalanced_Solution(TreeNode* root) {
        depth(root);
        return judge(root);
    }
};

时间复杂度:O(N)
空间复杂度:O(N)

##方法二:自底向上
方法一是先求出以每个结点为根的树的高度,然后再判断,其实可以直接再求高度的同时,直接判断即可。
利用后序遍历:左子树、右子树、根节点,可以先递归到叶子节点,然后在回溯的过程中来判断是否满足条件。
求树的高度的代码为:

int depth(TreeNode *root) {
    if (!root) return 0;
    int ldep = depth(root-&gt;left);
    int rdep = depth(root-&gt;right);
    return max(ldep, rdep) + 1;
}

然后对上述代码加以改造,如果不满足平衡二叉树的定义,则返回-1,并且如果左子树不满足条件了,直接返回-1,右子树也是如此,相当于剪枝,加速结束递归。
代码如下:

int depth(TreeNode *root) {
    if (!root) return 0;
    int ldep = depth(root-&gt;left);
    if (ldep == -1) return -1;
    int rdep = depth(root-&gt;right);
    if (rdep == -1) return -1;
    int sub = abs(ldep - rdep);
    if (sub &gt; 1) return -1;
    return max(ldep, rdep) + 1;
}

最后只需要判断depth(root)返回的是否为-1,如果是-1,则不是,否则,则是。
代码如下:

class Solution {
public:
    int depth(TreeNode *root) {
        if (!root) return 0;
        int ldep = depth(root-&gt;left);
        if (ldep == -1) return -1;
        int rdep = depth(root-&gt;right);
        if (rdep == -1) return -1;
        int sub = abs(ldep - rdep);
        if (sub &gt; 1) return -1;
        return max(ldep, rdep) + 1;
    }
    bool IsBalanced_Solution(TreeNode* root) {
        return depth(root) != -1;
    }
};

时间复杂度:O(N)
空间复杂度:O(N)</treenode*,></treenode*,></treenode*,>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值