周赛137
leetcode 1046. 最后一块石头的重量
public int lastStoneWeight(int[] stones) {
PriorityQueue<Integer> q = new PriorityQueue<>(new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for(int i:stones)
q.add(i);
while (q.size() > 1){
int max1 = q.poll();
int max2 = q.poll();
q.add(max1 - max2);
}
return q.peek();
}
leetcode 1047. 删除字符串中的所有相邻重复项
解题思路:利用栈先入后出的特点,比较栈顶元素和字符串元素
public String removeDuplicates(String S) {
Stack<Character> s = new Stack<>();
for(int i = 0;i < S.length();i++){
if(!s.isEmpty() && s.peek() == S.charAt(i)){
s.pop();
} else {
s.push(S.charAt(i));
}
}
StringBuffer res = new StringBuffer();
while (!s.isEmpty()){
res.append(s.pop());
}
return res.reverse().toString();
}
leetcode 1048. 最长字符串链
解题思路:动态规划求解当前单词的最长链, length[word2] = max(length[word2], length[word] + 1)
public int longestStrChain(String[] words) {
int res = 0;
int[] dp = new int[words.length + 1];
Arrays.fill(dp,1);
Arrays.sort(words,new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
for(int i = 0;i < words.length;i++){
for(int j = i + 1;j < words.length;j++){
if(words[i].length() + 1 < words[j].length())
break;
if(words[i].length() + 1 == words[j].length() && ispre(words[i],words[j])) {
dp[j] = Math.max(dp[j],dp[i] + 1);
}
}
res = Math.max(res,dp[i]);
}
return res;
}
public boolean ispre(String word1,String word2){
int i = 0,j = 0;
while(i < word1.length() && j < word2.length()){
if(word1.charAt(i) == word2.charAt(j)){
i++;
}
j++;
}
if(i == word1.length())
return true;
return false;
}
leetcode 1049. 最后一块石头的重量 II
解题思路:题1046的进阶,转换为背包问题,对数组stones求和,对于容量为sum/2的背包,放入石头,满足背包的重量最大,粉碎石头的最小重量 = sum - 2 * 背包内最大石头重量
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int i:stones){
sum+=i;
}
int res = sum / 2;
int[] dp = new int[res+1];
for(int i = 0;i < stones.length;i++) {
for (int j = res;j >= stones[i];j--) {
dp[j] = Math.max(dp[j], dp[j-stones[i]]+stones[i]);
}
}
return sum - 2 * dp[res];
}