力扣爆刷第164天之TOP100五连刷86-90(最大数、不同路径、买卖股票)
文章目录
一、179. 最大数
题目链接:https://leetcode.cn/problems/largest-number/description/
思路:给一个数组,求把数组里的数作为字符串进行拼接,要求拼接成最大的数,其实就是一个字符串排序问题,那么长短不一的字符串如何简单的求大小呢?其实很简单,长度不一样,改成一样的就可以了,如3, 30,可以让a+b和b+a比较,此为升序,b+a和a+b此为降序。
class Solution {
public String largestNumber(int[] nums) {
String[] source = new String[nums.length];
for(int i = 0; i < nums.length; i++) source[i] = nums[i] + "";
Arrays.sort(source, (a, b) -> (b+a).compareTo(a+b));
if(source[0].charAt(0) == '0') return "0";
StringBuilder res = new StringBuilder();
for(String s : source) res.append(s);
return res.toString();
}
}
二、227. 基本计算器 II
题目链接:https://leetcode.cn/problems/basic-calculator-ii/description/
思路:s = “3+2*2”,求类似这种的表达式,一般都是依赖于栈,看到题目第一时间要有这个想法,其他的就是只需要维护好一个符号位记录前一个位置的符号,然后用栈来优先处理乘法和除法,遇到加法、减法都先把对应的符合与数先压栈,遇到乘法或除法都出栈进行运算,这样最后栈内只剩下正数和负数。然后全部出栈即可。
class Solution {
public int calculate(String s) {
LinkedList<Integer> stack = new LinkedList<>();
int n = 0;
char sign = '+';
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(c >= '0' && c <= '9') {
n = n * 10 + (c - '0');
}
if(c == '+' || c == '-' || c == '*' || c == '/' || i == s.length()-1) {
switch(sign) {
case '+' : stack.push(n);
break;
case '-' : stack.push(-n);
break;
case '*' : stack.push(stack.pop() * n);
break;
case '/' : stack.push(stack.pop() / n);
break;
}
sign = c;
n = 0;
}
}
n = 0;
while(!stack.isEmpty()) n += stack.pop();
return n;
}
}
三、62. 不同路径
题目链接:https://leetcode.cn/problems/unique-paths/description/
思路:经典动态规划题,状态转移方程从题目描述中就可以看出来,每一个位置可以由它的左方或者上方来,那么定义dp[i][j]表示抵达nums[i][j]有多少种方法,那么dp[i][j] = dp[i-1][j] + dp[i][j+1]。其他的没什么,注意初始化。
class Solution {
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
dp[0] = 1;
for(int i = 0; i < m; i++) {
for(int j = 1; j < n; j++) {
dp[j] += dp[j-1];
}
}
return dp[n-1];
}
}
四、83. 删除排序链表中的重复元素
题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-list/description/
思路:删除链表中重复元素,只需要维护三个指针,a,b,c分别记录前一个节点、当前节点、下一个节点。维护前一个节点是为了方便删除当前这个重复的节点。
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null) return head;
ListNode pro = head, cur = head.next, pre = null;
while(cur != null) {
pre = cur.next;
if(cur.val == pro.val) pro.next = cur.next;
else pro = cur;
cur = pre;
}
return head;
}
}
五、122. 买卖股票的最佳时机 II
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/
思路:本题是每一天都可以进行买卖,可以用贪心,也可以用动态规划。
贪心的话即为,每次交易只要收益大于0就进行交易,最后交易额一定最大。
class Solution {
public int maxProfit(int[] prices) {
int res = 0;
for(int i = 1; i < prices.length; i++) {
if(prices[i] > prices[i-1]) res += prices[i] - prices[i-1];
}
return res;
}
}
动态规划做法,对于股票买卖类型的题,每一天都有两种状态,即为持有股票或不持有股票,对于持有股票可以是之前就已经持有了,也可以是今天才持有。对于不持有股票,可以是今天才不持有,也可以是之前就已经不持有了。
class Solution {
public int maxProfit(int[] prices) {
int[] dp = new int[2];
dp[0] = -prices[0];
for(int i = 1; i < prices.length; i++) {
dp[0] = Math.max(dp[0], dp[1] - prices[i]);
dp[1] = Math.max(dp[1], dp[0] + prices[i]);
}
return dp[1];
}
}