zoukankan      html  css  js  c++  java
  • LeetCode解题总结(2)

    LeetCode解题总结(2)

    6. ZigZag Conversion

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

    Example 1:

    Input: s = "PAYPALISHIRING", numRows = 3
    Output: "PAHNAPLSIIGYIR"
    
    P   A   H   N
    A P L S I I G
    Y   I   R
    

    Example 2:

    Input: s = "PAYPALISHIRING", numRows = 4
    Output: "PINALSIGYAHRPI"
    Explanation:
    
    P     I    N
    A   L S  I G
    Y A   H R
    P     I   
    

    思路

    根据题目给出的图,可以找出规律,看到每 2 * numRows - 2 个字符组成一组,形成一个ZigZag。然后除了第一行和最后一行是每组一个字符,其他行都是每组两个字符。而首尾两行的规律是每隔 (2 * numRows - 2) 一个字符,其他行则是按照规律,如果下行段,同样是 (2 * numRows - 2) 的间隔,而上行段则是倒过来填充的规律,如果在第curRow行,则为 (2 * numRows - 2 - curRow % (2 * numRows - 2)) 的位置上的字符

    class Solution {
    public:
        string convert(string s, int numRows) {
    		if (numRows < 2)
    		{
    			return s;
    		}
    		int step = (2 * numRows - 2);
    		int size = s.size();
    
    		string res;
    		res.resize(size);
    
    		int i = 0;
    		int curRow = 0;
    		for (int j = 0; j < size; ++j)
    		{
    			res[j] = s[i];
    			if (curRow == 0 || curRow == numRows - 1)
    			{
    				i += step;
    			}
    			else
    			{
    				if (i % step < numRows)
    				{
    					i = i + step - 2 * curRow;
    				}
    				else
    				{
    					i = i + step - (i - curRow) % step;
    				}
    			}
    
    			if (i >= size)
    			{
    				++curRow;
    				i = curRow;
    			}
    		}
    
    		return res;
        }
    };
    

    7. Reverse Integer

    Given a 32-bit signed integer, reverse digits of an integer.

    思路

    题目思路很简单,只需要按10进制位每次取模后,就可以取出最低位,然后就加到新的数字上即可。可以理解为堆栈的形式,从旧数字中弹出最低位再压入新数字中作为最低位。然后需要特别注意的就是整形的边界问题,所以需要在添加的时候先做检查。

    class Solution {
    public:
        int reverse(int x) {
            if (x == INT_MIN) return 0;
            int max = INT_MAX / 10;
            int res = 0;
            bool carry = false;
            if (x < 0) 
            {
                x = -x;
                carry = true;
            }
            while (x > 0)
            {
                if (res > max) return 0;
                    
                res = res * 10 + x % 10;
                x /= 10;
            }
            
            if (carry)
            {
                return -res;
            }
            return res;
        }
    };
    

    8. String to Integer (atoi)

    Implement atoi which converts a string to an integer.

    The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

    The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

    If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

    If no valid conversion could be performed, a zero value is returned.

    Note:

    • Only the space character ' ' is considered as whitespace character.
    • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.

    Example 1:

    Input: "42"
    Output: 42
    

    Example 2:

    Input: "   -42"
    Output: -42
    Explanation: The first non-whitespace character is '-', which is the minus sign. Then take as many numerical digits as possible, which gets 42.
    

    Example 3:

    Input: "4193 with words"
    Output: 4193
    Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.
    

    Example 4:

    Input: "words and 987"
    Output: 0
    Explanation: The first non-whitespace character is 'w', which is not a numerical digit or a +/- sign. Therefore no valid conversion could be performed.
    

    Example 5:

    Input: "-91283472332"
    Output: -2147483648
    Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer. Thefore INT_MIN (−231) is returned.
    

    思路

    题目很容易理解,但是可以看出有几个异常和边界的情况需要处理,首先需要确定字符串第一位合法字符在什么位置,然后从该位置开始往后读取出一个整数,知道下一个非法字符为止,然后还需要判断数字是否超过整形的边界,如果超过,就会限制到INT_MAX和INT_MIN之间。

    class Solution {
    public:
        int myAtoi(string str) {
            int ret = 0;
            bool carry = false;
            int i = 0;
            int size = str.size();
            
            //判断空格
            while (i < size && str[i] == ' ') ++i;
            
            //判断符号
            if (i < size && str[i] == '-') carry = true;
            if (i < size && (str[i] == '+' || str[i] == '-')) ++i;
            
            int max = INT_MAX / 10;
            for (; i < size; ++i)
            {
                if (str[i] < '0' || str[i] > '9')
                {
                    break;
                }
                
                //溢出情况1
                if (ret > max)
                {
                    if (carry) return INT_MIN;
                    return INT_MAX;
                }
                
                //溢出情况2
                int num = str[i] - '0';
                if (ret == max)
                {
                    if (carry)
                    {
                        if (num > 7) return INT_MIN;
                    }
                    else
                    {
                        if (num > 6) return INT_MAX;
                    }
                }
                
                //不溢出
                ret = ret * 10 + num;
            }
            
            
            if (carry) return -ret;
            return ret;
        }
    };
    

    9. Palindrome Number

    Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.

    Example 1:

    Input: 121
    Output: true
    

    Example 2:

    Input: -121
    Output: false
    Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
    

    Example 3:

    Input: 10
    Output: false
    Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
    

    思路

    看到例子,可以知道回文数首先需要是一个正数。然后也可以发现,如果a是回文数,那么从最低位往前弹出数字拼装一个不小于a的新数字b,a要不等于b,要不等于b/10。

    class Solution {
    public:
        bool isPalindrome(int x) {
            if(x < 0 || (x % 10 == 0 && x != 0)) {
                return false;
            }
    
            int res = 0;
            while(x > res) {
                res = res * 10 + x % 10;
                x /= 10;
            }
            
            return x == res || x == res / 10;
        }
    };
    

    10. Regular Expression Matching

    Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.

    '.' Matches any single character.
    '*' Matches zero or more of the preceding element.
    

    The matching should cover the entire input string (not partial).

    Note:

    • s could be empty and contains only lowercase letters a-z.
    • p could be empty and contains only lowercase letters a-z, and characters like . or *.

    Example 1:

    Input:
    s = "aa"
    p = "a"
    Output: false
    Explanation: "a" does not match the entire string "aa".
    

    Example 2:

    Input:
    s = "aa"
    p = "a*"
    Output: true
    Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
    

    Example 3:

    Input:
    s = "ab"
    p = ".*"
    Output: true
    Explanation: ".*" means "zero or more (*) of any character (.)".
    

    Example 4:

    Input:
    s = "aab"
    p = "c*a*b"
    Output: true
    Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".
    

    Example 5:

    Input:
    s = "mississippi"
    p = "mis*is*p*."
    Output: false
    

    思路

    分析题目,可以知道这是一道典型的递归题。难点在于 * 号的判断,如果p[pi + 1]为 *,那么要不p(pi, end) == s(si, end), 要不p(pi+2, end) == s(si, end)。具体划分情况如下:

    • 如果p[pi+1] == *,将pi和pi+1作为一个匹配的字符串,那么有两种情况:
        1. 如果p[pi] == s[si],此时,选择需要pi,si往后一位,判断p(pi,end)和s(si+1, end)。
        1. 如果p[pi] != s[si],此时,pi无法被选择,那么 * 也是应该舍弃的,直接判断p(pi+2, end)和s(si,end)。
    • 如果p[pi+1] != * , 那么p如果和s匹配,必然p[pi] == s[si],也就是第一位相等(包括p[pi]为.的情况),同时,需要各自往后移一位,判断 p(pi+1, end)和s(si+1, end)是否相等。

    第一步的简单递归就可以通过上述分析的3种情况来完成。但是时间需要的太久,可以看出,如果需要判断p(pi, end)和s(si, end)是否匹配,可能存在情况:

      1. p(pi - 2, end)和s(si, end)
      1. p(pi - 1, end)和s(si - 1, end)
      1. p(pi, end)和s(si - 1, end)

    那么从p(pi - 2, end)和s(si - 2, end)到p(pi, end)和s(si, end),有可能是经过路径1->路径3,也有可能是经过路径2->路径2,这样就会有重复的情况发生,此时可以联想到使用动态规划记录中间经过的路径来减少判断。最终的解法如下:

    class Solution {
    public:
    	bool partMatch(string& s, string& p, int sI, int pI)
    	{
    		if (dpArr[sI][pI] >= 0)
    		{
    			return dpArr[sI][pI];
    		}
    		if (pI >= p.size()) return sI >= s.size();
    
    		bool firstMatch = sI < s.size() && (s[sI] == p[pI] || p[pI] == '.');
    
    		bool res = false;
    		if (pI + 1 < p.size() && p[pI + 1] == '*')
    		{
    			res = partMatch(s, p, sI, pI + 2) || (firstMatch && partMatch(s, p, sI + 1, pI));
    		}
    		else
    		{
    			if (!firstMatch)
    				res = false;
    			else
    				res = partMatch(s, p, sI + 1, pI + 1);
    		}
    
    		dpArr[sI][pI] = res;
    		return res;
    	}
    
    	bool isMatch(string s, string p) {
    		dpArr.resize(s.size() + 1);
    		for (auto i = 0; i <= s.size(); ++i)
    		{
    			dpArr[i].resize(p.size() + 1, -1);
    		}
    
    		auto res = partMatch(s, p, 0, 0);
    
    		for (auto i = 0; i <= s.size(); ++i)
    		{
    			dpArr[i].clear();
    		}
    		dpArr.clear();
    
    		return res;
    	}
    
    	vector<vector<char>> dpArr;
    };
    
    
  • 相关阅读:
    Java多线程
    2018腾讯校招软件开发岗在线笔试题
    2018京东校招Java笔试题
    计模式之中介者、观察者
    值得注意的Java基础知识
    Java的内部类
    用静态内部类实现单例模式
    String,StringBuilder区别,一个是常量,一个是可变量
    ArrayList list = new ArrayList()在这个泛型为Integer的ArrayList中存放一个String类型的对象
    List<String> list=new ArrayList<String>(20);为什么要声明为List 而不是ArrayList<String>?
  • 原文地址:https://www.cnblogs.com/zhqherm/p/11924805.html
Copyright © 2011-2022 走看看