LeetCode 8~14題
阿新 • • 發佈:2020-12-23
第八題:
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
}