本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1219. 黄金矿工
2022.2.5 每日一题
题目描述
你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m * n 的网格 grid 进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量;如果该单元格是空的,那么就是 0。
为了使收益最大化,矿工需要按以下规则来开采黄金:
每当矿工进入一个单元,就会收集该单元格中的所有黄金。 矿工每次可以从当前位置向上下左右四个方向走。 每个单元格只能被开采(进入)一次。 不得开采(进入)黄金数目为 0 的单元格。 矿工可以从网格中 任意一个 有黄金的单元格出发或者是停止。
示例 1:
输入:grid = [[0,6,0],[5,8,7],[0,9,0]] 输出:24 解释: [[0,6,0], [5,8,7], [0,9,0]] 一种收集最多黄金的路线是:9 -> 8 -> 7。
示例 2:
输入:grid = [[1,0,7],[2,0,6],[3,4,5],[0,3,0],[9,0,20]] 输出:28 解释: [[1,0,7], [2,0,6], [3,4,5], [0,3,0], [9,0,20]] 一种收集最多黄金的路线是:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7。
提示:
1 <= grid.length, grid[i].length <= 15 0 <= grid[i][j] <= 100 最多 25 个单元格中有黄金。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/pa… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
回溯
class Solution {
int[][] dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int[][] grid;
int m;
int n;
public int getMaximumGold(int[][] grid) {
//格子比较少,且黄金比较少,所以就回溯应该可以
this.grid = grid;
m = grid.length;
n = grid[0].length;
int res = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(grid[i][j] == 0)
continue;
boolean[][] used = new boolean[m][n];
used[i][j] = true;
int t = find(used, i, j, grid[i][j]);
res = Math.max(res, t);
used[i][j] = false;
}
}
return res;
}
public int find(boolean[][] used, int i, int j, int gold){
int res = gold;
for(int[] d : dir){
int x = i + d[0];
int y = j + d[1];
if(x >= 0 && y >= 0 && x < m && y < n && !used[x][y] && grid[x][y] != 0){
used[x][y] = true;
res = Math.max(res, find(used, x, y, gold + grid[x][y]));
used[x][y] = false;
}
}
return res;
}
}
1748. 唯一元素的和
2022.2.6 每日一题
题目描述
给你一个整数数组 nums 。数组中唯一元素是那些只出现 恰好一次 的元素。
请你返回 nums 中唯一元素的 和 。
示例 1:
输入:nums = [1,2,3,2] 输出:4 解释:唯一元素为 [1,3] ,和为 4 。
示例 2:
输入:nums = [1,1,1,1,1] 输出:0 解释:没有唯一元素,和为 0 。
示例 3 :
输入:nums = [1,2,3,4,5] 输出:15 解释:唯一元素为 [1,2,3,4,5] ,和为 15 。
提示:
1 <= nums.length <= 100 1 <= nums[i] <= 100
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/su… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
class Solution {
public int sumOfUnique(int[] nums) {
int[] count = new int[101];
for(int i = 0; i < nums.length; i++){
count[nums[i]]++;
}
int res = 0;
for(int i = 0; i < 101; i++){
if(count[i] == 1)
res += i;
}
return res;
}
}
1405. 最长快乐字符串
2022.2.7 每日一题,开工大吉
题目描述
如果字符串中不含有任何 'aaa','bbb' 或 'ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。
给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。 s 中 最多 有a 个字母 'a'、b 个字母 'b'、c 个字母 'c' 。 s 中只含有 'a'、'b' 、'c' 三种字母。
如果不存在这样的字符串 s ,请返回一个空字符串 ""。
示例 1:
输入:a = 1, b = 1, c = 7 输出:"ccaccbcc" 解释:"ccbccacc" 也是一种正确答案。
示例 2:
输入:a = 2, b = 2, c = 1 输出:"aabbc"
示例 3:
输入:a = 7, b = 1, c = 0 输出:"aabaa" 解释:这是该测试用例的唯一正确答案。
提示:
0 <= a, b, c <= 100 a + b + c > 0
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/lo… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
思路其实很简单,因为不能连续放三个,所以最多连续放两个 那么该怎么摆放呢 我们能想到的最简单的情况就是如果三个字母相同的话,一个一个放就可以了,所以我们想到的目标就是使三个字母个数相同 如果两个字母数目相同且大于第三个字母的个数呢,两个相同的字母一个一个放,那么就会和第三个字母个数相同 那如果三个字母个数都不相同,那么最多的放两个,次多的放一个,这样就会向第二种情况靠近
我写的比较复杂,因为想不到简单的写法,需要注意各种空指针的情况
class Solution {
public String longestDiverseString(int a, int b, int c) {
//怎么摆放比较合适呢,应该是三个字母个数差不多相同
//那么按这样来的话,摆放的策略就是先摆放最多的字母,
//然后摆放第二多的,如果两个字母相同了,那么就一直放两个,直到和第三个相同
//然后三个轮流摆放
StringBuffer sb = new StringBuffer();
PriorityQueue<int[]> pq = new PriorityQueue<>((x, y) -> (y[1] - x[1]));
if(a != 0)
pq.offer(new int[]{1, a});
if(b != 0)
pq.offer(new int[]{2, b});
if(c != 0)
pq.offer(new int[]{3, c});
while(!pq.isEmpty()){
int t = helper(pq);
if(t == 1){
int[] first = pq.poll();
sb.append((char)(first[0] - 1 + 'a'));
if(first[1] - 1 > 0)
sb.append((char)(first[0] - 1 + 'a'));
if(pq.isEmpty())
return sb.toString();
int[] second = pq.poll();
sb.append((char)(second[0] - 1 + 'a'));
if(first[1] - 2 > 0)
pq.offer(new int[]{first[0], first[1] - 2});
if(second[1] - 1 > 0)
pq.offer(new int[]{second[0], second[1] - 1});
}else if(t == 2){
int[] first = pq.poll();
int[] second = pq.poll();
sb.append((char)(first[0] - 1 + 'a'));
sb.append((char)(second[0] - 1 + 'a'));
if(first[1] - 1 > 0)
pq.offer(new int[]{first[0], first[1] - 1});
if(second[1] - 1 > 0)
pq.offer(new int[]{second[0], second[1] - 1});
}else{
int[] first = pq.poll();
int[] second = pq.poll();
int[] third = pq.poll();
int num = first[1];
while(num-- > 0){
sb.append((char)(first[0] - 1 + 'a'));
sb.append((char)(second[0] - 1 + 'a'));
sb.append((char)(third[0] - 1 + 'a'));
}
return sb.toString();
}
}
return sb.toString();
}
//如果最大的比第二大的大,那么就返回1
//如果前两个相同,比第三个大,返回2
//如果三个相同,返回3
public int helper(PriorityQueue<int[]> pq){
if(pq.size() == 1)
return 1;
int[] first = pq.poll();
int[] second = pq.poll();
int[] third = pq.peek();
int flag = 0;
if(first[1] > second[1])
flag = 1;
else if(third == null || second[1] > third[1])
flag = 2;
else
flag = 3;
pq.offer(first);
pq.offer(second);
return flag;
}
}
其实按照构建的字符串,判断是否三个字符相连,如果有三个相同字符相连,那么就用第二多的,这样写简单点