1. 程式人生 > 其它 >LeetCode 8~14題

LeetCode 8~14題

技術標籤:每日演算法題目leetcode

第八題:

class Solution {
public:
    int myAtoi(string str) {
        int k = 0;
        while (k < str.size() && str[k] == ' ') k ++ ;
        if (k == str.size()) return 0;

        int minus = 1;
        if (str[k] == '-') minus = -1, k ++ ;
        else if (str[k] ==
'+') k ++ ; int res = 0; while (k < str.size() && str[k] >= '0' && str[k] <= '9') { int x = str[k] - '0'; if (minus > 0 && res > (INT_MAX - x) / 10) return INT_MAX; if (minus < 0 && -res < (INT_MIN + x)
/ 10) return INT_MIN; if (-res * 10 - x == INT_MIN) return INT_MIN; res = res * 10 + x; k ++ ; if (res > INT_MAX) break; } res *= minus; return res; } };
INT_MAX = 2 ** 31 - 1
INT_MIN = -2 ** 31

class Automaton:
    def __init__
(self): self.state = 'start' self.sign = 1 self.ans = 0 self.table = { 'start': ['start', 'signed', 'in_number', 'end'], 'signed': ['end', 'end', 'in_number', 'end'], 'in_number': ['end', 'end', 'in_number', 'end'], 'end': ['end', 'end', 'end', 'end'], } def get_col(self, c): if c.isspace(): return 0 if c == '+' or c == '-': return 1 if c.isdigit(): return 2 return 3 def get(self, c): self.state = self.table[self.state][self.get_col(c)] if self.state == 'in_number': self.ans = self.ans * 10 + int(c) self.ans = min(self.ans, INT_MAX) if self.sign == 1 else min(self.ans, -INT_MIN) elif self.state == 'signed': self.sign = 1 if c == '+' else -1 class Solution: def myAtoi(self, str: str) -> int: automaton = Automaton() for c in str: automaton.get(c) return automaton.sign * automaton.ans
class Solution {
    public int myAtoi(String str) {
        Automaton automaton = new Automaton();
        int length = str.length();
        for (int i = 0; i < length; ++i) {
            automaton.get(str.charAt(i));
        }
        return (int) (automaton.sign * automaton.ans);
    }
}

class Automaton {
    public int sign = 1;
    public long ans = 0;
    private String state = "start";
    private Map<String, String[]> table = new HashMap<String, String[]>() {{
        put("start", new String[]{"start", "signed", "in_number", "end"});
        put("signed", new String[]{"end", "end", "in_number", "end"});
        put("in_number", new String[]{"end", "end", "in_number", "end"});
        put("end", new String[]{"end", "end", "end", "end"});
    }};

    public void get(char c) {
        state = table.get(state)[get_col(c)];
        if ("in_number".equals(state)) {
            ans = ans * 10 + c - '0';
            ans = sign == 1 ? Math.min(ans, (long) Integer.MAX_VALUE) : Math.min(ans, -(long) Integer.MIN_VALUE);
        } else if ("signed".equals(state)) {
            sign = c == '+' ? 1 : -1;
        }
    }

    private int get_col(char c) {
        if (c == ' ') {
            return 0;
        }
        if (c == '+' || c == '-') {
            return 1;
        }
        if (Character.isDigit(c)) {
            return 2;
        }
        return 3;
    }
}
func myAtoi(str string) int {
	return convert(clean(str))
}

func clean(s string) (sign int, abs string) {
	// 先去除首尾空格
	s = strings.TrimSpace(s)
	if s == "" {
		return
	}
	// 判斷第一個字元
	switch s[0] {
	// 有效的
	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		sign, abs = 1, s
	// 有效的,正號
	case '+':
		sign, abs = 1, s[1:]
	// 有效的,負號
	case '-':
		sign, abs = -1, s[1:]
	// 無效的,當空字元處理,並且直接返回
	default:
		abs = ""
		return
	}
	for i, b := range abs {
		// 遍歷第一波處理過的字元,如果直到第i個位置有效,那就取s[:i],從頭到這個有效的字元,剩下的就不管了,也就是break掉
		// 比如 s=123abc,那麼就取123,也就是s[:3]
		if b < '0' || '9' < b {
			abs = abs[:i]
			// 一定要break,因為後面的就沒用了
			break
		}
	}
	return
}

// 接收的輸入是已經處理過的純數字
func convert(sign int, absStr string) int {
	absNum := 0
	for _, b := range absStr {
		// b - '0' ==> 得到這個字元型別的數字的真實數值的絕對值
		absNum = absNum*10 + int(b-'0')
		// 檢查溢位
		switch {
		case sign == 1 && absNum > math.MaxInt32:
			return math.MaxInt32
		// 這裡和正數不一樣的是,必須和負號相乘,也就是變成負數,否則永遠走不到裡面
		case sign == -1 && absNum*sign < math.MinInt32:
			return math.MinInt32
		}
	}
	return sign * absNum
}

第九題:

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) return 0;
        int y = x;
        long long res = 0;
        while (x) {
            res = res * 10 + x % 10;
            x /= 10;
        }
        return res == y;
    }
};
class Solution {
    public boolean isPalindrome(int x) {
        // 特殊情況:
        // 如上所述,當 x < 0 時,x 不是迴文數。
        // 同樣地,如果數字的最後一位是 0,為了使該數字為迴文,
        // 則其第一位數字也應該是 0
        // 只有 0 滿足這一屬性
        if (x < 0 || (x % 10 == 0 && x != 0)) {
            return false;
        }

        int revertedNumber = 0;
        while (x > revertedNumber) {
            revertedNumber = revertedNumber * 10 + x % 10;
            x /= 10;
        }

        // 當數字長度為奇數時,我們可以通過 revertedNumber/10 去除處於中位的數字。
        // 例如,當輸入為 12321 時,在 while 迴圈的末尾我們可以得到 x = 12,revertedNumber = 123,
        // 由於處於中位的數字不影響迴文(它總是與自己相等),所以我們可以簡單地將其去除。
        return x == revertedNumber || x == revertedNumber / 10;
    }
}
func isPalindrome(x int) bool {
    // 特殊情況:
    // 如上所述,當 x < 0 時,x 不是迴文數。
    // 同樣地,如果數字的最後一位是 0,為了使該數字為迴文,
    // 則其第一位數字也應該是 0
    // 只有 0 滿足這一屬性
    if x < 0 || (x % 10 == 0 && x != 0) {
        return false
    }

    revertedNumber := 0
    for x > revertedNumber {
        revertedNumber = revertedNumber * 10 + x % 10
        x /= 10
    }

    // 當數字長度為奇數時,我們可以通過 revertedNumber/10 去除處於中位的數字。
    // 例如,當輸入為 12321 時,在 while 迴圈的末尾我們可以得到 x = 12,revertedNumber = 123,
    // 由於處於中位的數字不影響迴文(它總是與自己相等),所以我們可以簡單地將其去除。
    return x == revertedNumber || x == revertedNumber / 10
}
class Solution:

    # 方法一: 將int轉化成str型別: 雙向佇列
    # 複雜度: O(n^2) [每次pop(0)都是O(n)..比較費時]
    def isPalindrome(x: int) -> bool:
        lst = list(str(x))
        while len(lst) > 1:
            if lst.pop(0) != lst.pop():
                return  False
        return True


    # 方法二: 將int轉化成str型別: 雙指標 (指標的效能一直都挺高的)
    # 複雜度: O(n)
    def isPalindrome(x: int) -> bool:
        lst = list(str(x))
        L, R = 0, len(lst)-1
        while L <= R:
            if lst[L] != lst[R]:
                return  False
            L += 1
            R -= 1
        return True


    # 方法三: 進階:不將整數轉為字串來解決: 使用log來計算x的位數
    # 複雜度: O(n)
    def isPalindrome(self, x: int) -> bool:
        """
        模仿上面字串的方法:分別取'第一位的數'與'第二位的數'對比
                        (弊端是:頻繁計算,導致速度變慢)(下面的方法三隻反轉一半數字,可以提高效能)
        """
        if x < 0:
            return False
        elif x == 0:
            return True
        else:
            import math
            length = int(math.log(x, 10)) + 1
            L = length-1
            print("l = ", L)
            for i in range(length//2):
                if x // 10**L != x % 10:
                    return False
                x = (x % 10**L) //10
                L -= 2
            return True

    # 方法四: 進階:不將整數轉為字串來解決: 使用log來計算x的位數
    # 複雜度: O(n)
    def isPalindrome(self, x: int) -> bool:
        """
        只反轉後面一半的數字!!(節省一半的時間)
        """
        if x < 0 or (x!=0 and x%10==0):
            return False
        elif x == 0:
            return True
        else:
            import math
            length = int(math.log(x, 10)) + 1
            reverse_x = 0
            for i in range(length//2):
                remainder = x % 10
                x = x // 10
                reverse_x = reverse_x * 10 + remainder
            # 當x為奇數時, 只要滿足 reverse_x == x//10 即可
            if reverse_x == x or reverse_x == x//10:
                return True
            else:
                return False

    # 方法五: 進階:不將整數轉為字串來解決: 不使用log函式
    # 複雜度: O(n)
    def isPalindrome(self, x: int) -> bool:
        """
        只反轉後面一半的數字!!(節省一半的時間)
        """
        if x < 0 or (x!=0 and x%10==0):
            return False
        elif x == 0:
            return True
        else:
            reverse_x = 0
            while x > reverse_x:
                remainder = x % 10
                reverse_x = reverse_x * 10 + remainder
                x = x // 10
            # 當x為奇數時, 只要滿足 reverse_x//10 == x 即可
            if reverse_x == x or reverse_x//10 == x:
                return True
            else:
                return False





x = 10
x = 10001
print(Solution().isPalindrome(x))

第十題:

class Solution {
public:
    bool isMatch(string s, string p) {
        int n = s.size(), m = p.size();
        s = ' ' + s, p = ' ' + p;
        vector<vector<bool>> f(n + 1, vector<bool>(m + 1));
        f[0][0] = true;
        for (int i = 0; i <= n; i ++ )
            for (int j = 1; j <= m; j ++ ) {
                if (j + 1 <= m && p[j + 1] == '*') continue;
                if (i && p[j] != '*') {
                    f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
                } else if (p[j] == '*') {
                    f[i][j] = f[i][j - 2] || i && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
                }
            }

        return f[n][m];
    }
};
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s), len(p)

        def matches(i: int, j: int) -> bool:
            if i == 0:
                return False
            if p[j - 1] == '.':
                return True
            return s[i - 1] == p[j - 1]

        f = [[False] * (n + 1) for _ in range(m + 1)]
        f[0][0] = True
        for i in range(m + 1):
            for j in range(1, n + 1):
                if p[j - 1] == '*':
                    f[i][j] |= f[i][j - 2]
                    if matches(i, j - 1):
                        f[i][j] |= f[i - 1][j]
                else:
                    if matches(i, j):
                        f[i][j] |= f[i - 1][j - 1]
        return f[m][n]
class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();

        boolean[][] f = new boolean[m + 1][n + 1];
        f[0][0] = true;
        for (int i = 0; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (p.charAt(j - 1) == '*') {
                    f[i][j] = f[i][j - 2];
                    if (matches(s, p, i, j - 1)) {
                        f[i][j] = f[i][j] || f[i - 1][j];
                    }
                } else {
                    if (matches(s, p, i, j)) {
                        f[i][j] = f[i - 1][j - 1];
                    }
                }
            }
        }
        return f[m][n];
    }

    public boolean matches(String s, String p, int i, int j) {
        if (i == 0) {
            return false;
        }
        if (p.charAt(j - 1) == '.') {
            return true;
        }
        return s.charAt(i - 1) == p.charAt(j - 1);
    }
}
func isMatch(s string, p string) bool {
    m, n := len(s), len(p)
    matches := func(i, j int) bool {
        if i == 0 {
            return false
        }
        if p[j-1] == '.' {
            return true
        }
        return s[i-1] == p[j-1]
    }

    f := make([][]bool, m + 1)
    for i := 0; i < len(f); i++ {
        f[i] = make([]bool, n + 1)
    }
    f[0][0] = true
    for i := 0; i <= m; i++ {
        for j := 1; j <= n; j++ {
            if p[j-1] == '*' {
                f[i][j] = f[i][j] || f[i][j-2]
                if matches(i, j - 1) {
                    f[i][j] = f[i][j] || f[i-1][j]
                }
            } else if matches(i, j) {
                f[i][j] = f[i][j] || f[i-1][j-1]
            }
        }
    }
    return f[m][n]
}

第十一題:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size() - 1;
        int max_area = 0;
        while (left < right) {
            int area = 0;
            int len = right - left;
            if (height[left] < height[right]) {
                area = height[left++] * len;
            } else {
                area = height[right--] * len;
            }
            if (area > max_area) max_area = area;
        }
        return max_area;
    }
};
public class Solution {
    public int maxArea(int[] height) {
        int l = 0, r = height.length - 1;
        int ans = 0;
        while (l < r) {
            int area = Math.min(height[l], height[r]) * (r - l);
            ans = Math.max(ans, area);
            if (height[l] <= height[r]) {
                ++l;
            }
            else {
                --r;
            }
        }
        return ans;
    }
}
class Solution:
    def maxArea(self, height: List[int]) -> int:
        l, r = 0, len(height) - 1
        ans = 0
        while l < r:
            area = min(height[l], height[r]) * (r - l)
            ans = max(ans, area)
            if height[l] <= height[r]:
                l += 1
            else:
                r -= 1
        return ans
func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}

func maxArea(height []int) int {
	o := 0
	i, j := 0, len(height)-1
	for i != j {
		hi, hj := height[i], height[j]
		s := (j - i) * min(hi, hj)
		if s > o {
			o = s
		}

		if hi > hj {
			j--
		} else {
			i++
		}
	}
	return o
}

第十二題:

class Solution {
public:
    string intToRoman(int num) {
        int values[] = {
            1000,
            900, 500, 400, 100,
            90, 50, 40, 10,
            9, 5, 4, 1
        };
        string reps[] = {
            "M",
            "CM", "D", "CD", "C",
            "XC", "L", "XL", "X",
            "IX", "V", "IV", "I",
        };

        string res;
        for (int i = 0; i < 13; i ++ ) {
            while (num >= values[i]) {
                num -= values[i];
                res += reps[i];
            }
        }

        return res;
    }
};
digits = [(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), 
          (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")]

def intToRoman(self, num: int) -> str:
    roman_digits = []
    # Loop through each symbol.
    for value, symbol in digits:
        # We don't want to continue looping if we're done.
        if num == 0: break
        count, num = divmod(num, value)
        # Append "count" copies of "symbol" to roman_digits.
        roman_digits.append(symbol * count)
    return "".join(roman_digits)
int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};    
String[] symbols = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

public String intToRoman(int num) {
    StringBuilder sb = new StringBuilder();
    // Loop through each symbol, stopping if num becomes 0.
    for (int i = 0; i < values.length && num >= 0; i++) {
        // Repeat while the current symbol still fits into num.
        while (values[i] <= num) {
            num -= values[i];
            sb.append(symbols[i]);
        }
    }
    return sb.toString();
}
func intToRoman(num int) string {
	roman := []string{"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"}
	intSlice := []int{1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000}
	s := ""
    x := len(intSlice) - 1
	for ; num != 0; {
		i := len(strconv.Itoa(num)) - 1
		n := (num / int(math.Pow10(i))) * int(math.Pow10(i))
		for ; x >= 0; x-- {
			if n >= intSlice[x] {
				s += roman[x]
				num -= intSlice[x]
				break
			}
		}
	}
	return s
}

第十三題:

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> hash;
        hash['I'] = 1, hash['V'] = 5;
        hash['X'] = 10, hash['L'] = 50;
        hash['C'] = 100, hash['D'] = 500;
        hash['M'] = 1000;

        int res = 0;
        for (int i = 0; i < s.size(); i ++ ) {
            if (i + 1 < s.size() && hash[s[i]] < hash[s[i + 1]])
                res -= hash[s[i]];
            else
                res += hash[s[i]];
        }

        return res;
    }
};
import java.util.*;

class Solution {
    public int romanToInt(String s) {
        int sum = 0;
        int preNum = getValue(s.charAt(0));
        for(int i = 1;i < s.length(); i ++) {
            int num = getValue(s.charAt(i));
            if(preNum < num) {
                sum -= preNum;
            } else {
                sum += preNum;
            }
            preNum = num;
        }
        sum += preNum;
        return sum;
    }
    
    private int getValue(char ch) {
        switch(ch) {
            case 'I': return 1;
            case 'V': return 5;
            case 'X': return 10;
            case 'L': return 50;
            case 'C': return 100;
            case 'D': return 500;
            case 'M': return 1000;
            default: return 0;
        }
    }
}
class Solution:
    def romanToInt(self, s: str) -> int:
        d = {'I':1, 'IV':3, 'V':5, 'IX':8, 'X':10, 'XL':30, 'L':50, 'XC':80, 'C':100, 'CD':300, 'D':500, 'CM':800, 'M':1000}
        return sum(d.get(s[max(i-1, 0):i+1], d[n]) for i, n in enumerate(s))
func RomanToInt(s string) (r int) {
	m := map[byte]int{
		'I': 1,
		'V': 5,
		'X': 10,
		'L': 50,
		'C': 100,
		'D': 500,
		'M': 1000,
	}
	pre := 0
	for i := len(s) - 1; i >= 0; i-- {
		cur := m[s[i]]
		if cur >= pre {
			r += cur
		} else {
			r -= cur
		}
		pre = cur
	}

	return r
}

第十四題:

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string res;
        if (strs.empty()) return res;

        for (int i = 0;; i ++ ) {
            if (i >= strs[0].size()) return res;
            char c = strs[0][i];
            for (auto& str: strs)
                if (str.size() <= i || str[i] != c)
                    return res;
            res += c;
        }

        return res;
    }
};
class Solution {
    public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        int minLength = Integer.MAX_VALUE;
        for (String str : strs) {
            minLength = Math.min(minLength, str.length());
        }
        int low = 0, high = minLength;
        while (low < high) {
            int mid = (high - low + 1) / 2 + low;
            if (isCommonPrefix(strs, mid)) {
                low = mid;
            } else {
                high = mid - 1;
            }
        }
        return strs[0].substring(0, low);
    }

    public boolean isCommonPrefix(String[] strs, int length) {
        String str0 = strs[0].substring(0, length);
        int count = strs.length;
        for (int i = 1; i < count; i++) {
            String str = strs[i];
            for (int j = 0; j < length; j++) {
                if (str0.charAt(j) != str.charAt(j)) {
                    return false;
                }
            }
        }
        return true;
    }
}
class Solution(object):
    def longestCommonPrefix(self, strs):
        ans = ''
        for i in zip(*strs):
            if len(set(i)) == 1:
                ans += i[0]
            else:
                break
        return ans
//GO
func longestCommonPrefix(strs []string) string {
    if len(strs) < 1 {
        return ""
    }
    prefix := strs[0]
    for _,k := range strs {
        for strings.Index(k,prefix) != 0 {
            if len(prefix) == 0 {
                return ""
            }
            prefix = prefix[:len(prefix) - 1]
        }
    }
    return prefix
}