开篇面试第22天-字符串相关

今天终于放下了心中的包袱,开始在公司看题了,毕竟靠晚上回家看真的不靠谱。一天下来,虽然进度还比较慢,但是看完了一个章节的课程,我是校招的时候在牛客网买的课程一直没看,这次正好能看看。


总结一下今天的题目吧:

  1. 判断一棵树是不是另一个棵树的子树:
    解题关键:这个题目的关键是先把树转为字符串,如果一个字符串是另一个字符串的子串,那树就是子树。核心的部分就是树转字符串。下面是一个递归的实现。
def tree2str(self, node):
        if node == None:
            return "#"
        nstring = str(node.val)
        nstring += self.tree2str(node.left)
        nstring += self.tree2str(node.right)
        return nstring
  1. 变形词:对于两个字符串A和B,如果A和B中出现的字符种类相同且每种字符出现的次数相同,则A和B互为变形词,请设计一个高效算法,检查两给定串是否互为变形词。
    解题关键:这个题目的关键是统计每种字符的出现的次数,就是用hash的方式,把每一个词都映射到hash表的一个位置,统计每个位置出现的次数,比较两个字符串的每个hash表的对应词的次数是否相等即可。下面是统计出现次数的函数。
def getwordtimes(self, A):
        result_dict = {}
        for i, ch in enumerate(A):
            if ch in result_dict:
                result_dict[ch] += 1
            else:
                result_dict
  1. 两串旋转:如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。比如A="12345",A的旋转词有"12345","23451","34512","45123"和"51234"。对于两个字符串A和B,请判断A和B是否互为旋转词。
    解题关键:这个题目的解题关键是先将A复制一份,接在A后面,变成一个大字符串,这样A中任何一个长度为len(A)的字符串都是A的旋转词。用C++实现的话还要考虑怎么判断子串,用python的话就直接用in函数就好了,比较简单。这里就不展示代码了。
  2. 句子的逆序:对于一个字符串,请设计一个算法,只在字符串的单词间做逆序调整,也就是说,字符串由一些由空格分隔的部分组成,你需要将这些部分逆序。比如"dog loves pig",变成"pig loves dog".(真重口味)
    解题关键:这个题目的解题关键是先对句子整体逆序,再对空格分割开的词内部逆序。而且大部分跟词顺序有关的题目都是利用这种思路,只不过逆序的位置会变动。如果用C++实现的话就需要两个指针,从首末两个位置同时向里移动,每移动一个位置,交换指针所指的元素,直到指针相遇。如果用python的话则简单很多,因为逆序可以用lists[::-1]来实现,所以这个题的代码(抄的别人的):
class Reverse:
    def reverseSentence(self, A, n):
        # write code here
        if n <= 1:
            return A
        a = A.split(' ')
        return " ".join(a[::-1])
  1. 最小字符串拼接:对于一个给定的字符串数组,请找到一种拼接顺序,使所有小字符串拼接成的大字符串是所有可能的拼接中字典序最小的。比如输入["abc","de"],2,返回"abcde"。
    解题关键:这个题目的关键在于比较顺序要比较的是两个字符串拼接以后的顺序,也就是对列表里的字符串进行排序,排序的原则是两个字符串拼接以后,新字符串中两个字符串的前后位置。比如"b"、"ba",看起来是b字典序比"ba"小,但是拼接以后,是"bab"最小,所以在列表中ba就要排在b的前面。可以用这种方式进行冒泡排序,这样就可以得到所有可能的拼接中字典序最小的字符串。这里的代码利用了python的sort函数,没有自己实现。
class Prior:
    def findSmallest(self, strs, n):
        # write code here
        strs.sort(cmp=lambda x,y :cmp(x+y,y+x))
        return ''.join(strs)
  1. 将字符串中的空格全部替换为“%20”。
    解题关键:这个题的关键就是要给字符串留出位置,当然其实python里可以直接用replace函数实现。在C++里呢,就需要先遍历得到空格的个数,然后将原来的字符串延长空格个数*2长度的字符串,新旧字符串同时从最后一个元素开始遍历,遇到旧字符串的值为字母,就原样赋值到新字符串,如果是空格,就依次添加0、2、%到新数组,指针向前移动,直到旧数组遍历完。上C++代码:
class Replacement {
public:
    string replaceSpace(string iniString, int length) {
        int count= 0;
            for(int i = 0; i < iniString.size(); i++)
                if(iniString[i] == ' ')
                    count++;
        if(count != 0)
            {
            //int j = 0;
            int j = length+count*2-1;
            string str = string (length+count*2,' ');
            for(int i = length-1; i >= 0; i--)
                {
                if(iniString[i] != ' ')
                    str[j--] = iniString[i];
                else
                    {
                    str[j--] = '0';
                    str[j--] = '2';
                    str[j--] = '%';
                }
            }
            return str;
        }
        return iniString;
    }
};
  1. 对于一个字符串,请设计一个算法,判断其是否为一个合法的括号串。
    解题关键:这个题的解题关键就是用一个数字记录,遇到左括号就加1,遇到右括号减1,如果在某个位置已经出现负数或者到结尾的时候不是0,就返回False。因为到某个位置为负数,说明右括号已经比左括号多了,所以左边可以有至少一个右括号是没有左括号可以匹配它,可怜的单身狗。
  2. 对于一个字符串,请设计一个高效算法,找到字符串的最长无重复字符的子串长度。
    解题关键:这个题就比较复杂一点了,解题的关键是需要两个变量,hash表变量map和pre,字符串为A,map是一个字典,记录当前字符上一次出现的位置,pre是一个数值,记录以i-1位置结尾的最长无重复子串的长度,其实也就是说到i位置这,上一个最长的无重复子串的长度,这时就要看i位置元素上一次出现在哪儿了,如果出现在pre左侧,那这次的最长就只能到达map[A[i]]位置了,因为再往前一个,前面的这段字符串里就会有重复的A[i]了,如果在pre的右侧,那就可以达到pre的位置了。其实原理也很简单,要求不重复的,肯定就是取短的那一段了,超过短的部分肯定就有重复了,所以for循环的比较部分,就是把短的距离赋值给以当前字符结尾的不重复子串长度tmp,如果是i-map[A[i]]短,那还需要把pre更新成当前的map[A[i]]。
# -*- coding:utf-8 -*-

class DistinctSubstring:
    def longestSubstring(self, A, n):
        # write code here
        # map记录字母上次出现的位置
        map = {}
        # max记录最长不重复字符串
        max = 0
        # tmp记录当前点的最长不重复字符串长度
        tmp = -1
        # pre记录当前节点上一次最长不重复串的长度
        pre = -1
        for i in range(n):
            if not map.has_key(A[i]):
                map[A[i]] = i
                tmp = i - pre
            else:
                # 如果A[i]上次出现的位置在pre右边
                # 那么tmp最大就是i-map[A[i]]
                if i - map[A[i]] < i - pre:
                    tmp = i - map[A[i]]
                    pre = map[A[i]]
                else:
                    tmp = i - pre
                map[A[i]] = i
            if tmp > max:
                max = tmp
        return max

总结

总的来说,涉及到二叉树的就需要结合二叉树序列化成字符串,如果是变形就涉及到逆序,再有就是要根据hash统计出现次数的,大概今天就学了这么多,都是左神的知识,我算是回顾一遍吧。
晚安,奋斗的孩子们。

你可能感兴趣的:(开篇面试第22天-字符串相关)