力扣爆刷第156天之TOP100五连刷46-50(字符串转整数、括号生成、两数相加)
文章目录
一、8. 字符串转换整数 (atoi)
题目链接:https://leetcode.cn/problems/string-to-integer-atoi/description/
思路:本题是把字符串转成整数,然后按照取出前置空格,前置0,的方式,只要读取了数字,后面遇到非数字部分直接返回,所以要从前往后逐步进行操作,首先就是取出前置空格,然后判断符号位,然后进入数字拼接部分,然后此处要注意是否超出界限。
所谓的超出界限,因为Integer.MAX_VALUE=2^31-1,我们每次拼接数字的时候都是把res*10+当前数,所以只要res>max再乘10一定超出了,又或者res = max,但最后一位数大于7,也超出了,这是因为Integer.MAX_VALUE的最后一位是7.
class Solution {
public int myAtoi(String s) {
if(s.length() == 0) return 0;
char[] list = s.toCharArray();
int res = 0, head = 1, i = 0, end = Integer.MAX_VALUE / 10;
while(i < list.length && list[i] == ' ') i++;
if(i == list.length) return 0;
if(list[i] == '-') head = -1;
if(list[i] == '-' || list[i] == '+') i++;
for(int j = i; j < list.length; j++) {
if(list[j] < '0' || list[j] > '9') break;
if(res > end || res == end && list[j] > '7') return head == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
res = res * 10 + (list[j] - '0');
}
return res * head;
}
}
二、22. 括号生成
题目链接:https://leetcode.cn/problems/generate-parentheses/description/
思路:括号生成,类似于排列,但又没必要提前拼接好再排列,可以在不指定起始位置然后进行回溯算法,每次都从索引0开始,就可以组合左右括号,然后正常递归收集,在收集完成后,需要判断生成的是否符合规则。规则通过计数实现,出现左括号+1,出现右括号-1,如果期间累加值为负数,则说明生成的括号非法。
class Solution {
char[] cList = {'(', ')'};
List<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
public List<String> generateParenthesis(int n) {
backTracking(n*2);
return list;
}
void backTracking(int n) {
if(sb.length() == n) {
if(isTrue()) {
list.add(sb.toString());
}
return;
}
for(int i = 0; i < 2; i++) {
sb.append(cList[i]);
backTracking(n);
sb.deleteCharAt(sb.length()-1);
}
}
boolean isTrue() {
int x = 0;
for(int i = 0; i < sb.length(); i++) {
char c = sb.charAt(i);
if(c == '(') x++;
else if(c == ')') x--;
if(x < 0) return false;
}
return x == 0;
}
}
三、70. 爬楼梯
题目链接:https://leetcode.cn/problems/climbing-stairs/description/
思路:爬楼梯也是经典动态规划题目了,类似于斐波那契数列,每次只能爬1个台阶或者2个台阶,那么也就是说其他抵达每一个台阶只依赖于该台阶的前两个台阶,只需要知道抵达这两个台阶有多少种方法,就能知道抵达当前台阶有多少种方法,由此维持两个状态即可,记录前两个位置。
class Solution {
public int climbStairs(int n) {
if(n < 3) return n;
int a = 1, b = 2, c = 0;
for(int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
}
四、2. 两数相加
题目链接:https://leetcode.cn/problems/add-two-numbers/description/
思路:链表节点相加,拼接为整数,只需要注意每次的进位即可,然后为了防止链表不等长,可以通过加0的方式替换,方便一个while中进行累加完。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int res = 0;
ListNode root = new ListNode(), p = root;
while(l1 != null || l2 != null) {
int a = l1 == null ? 0 : l1.val;
int b = l2 == null ? 0 : l2.val;
int sum = a + b + res;
ListNode t = new ListNode(sum % 10);
res = sum / 10;
p.next = t;
p = t;
l1 = l1 == null ? l1 : l1.next;
l2 = l2 == null ? l2 : l2.next;
}
if(res == 1) p.next = new ListNode(res);
return root.next;
}
}
五、165. 比较版本号
题目链接:https://leetcode.cn/problems/compare-version-numbers/description/
思路:比较版本号,其实就是数字比较,但是关键点在于,两个字符串中的每一组数字如何比较,其实就是用“.”来划分数字,两个字符串,一个一个来,第一个字符串计算出一个数字,然后等第二个计算,计算完再比较,然后再进入下一轮。
class Solution {
public int compareVersion(String version1, String version2) {
int i = 0, j = 0, m = version1.length(), n = version2.length();
while(i < m || j < n) {
int a = 0;
for(; i < m; i++) {
char c = version1.charAt(i);
if(c == '.') break;
a += a * 10 + (c - '0');
}
int b = 0;
for(; j < n; j++) {
char c = version2.charAt(j);
if(c == '.') break;
b += b * 10 + (c - '0');
}
if(a != b) return a > b ? 1 : -1;
i++;
j++;
}
return 0;
}
}