力扣第59场双周赛与第255场周赛总结解析
date: 2021-08-22 15:19:02
tags: [dfs,数学,图,竞赛,总结]
categories: 算法
经过昨晚的双周赛以及今日午时的周赛,继续感到自己的实力薄弱。双周赛一题,周赛两题。什么时候我也能来个AC呢?不说了,直接开始总结分析吧。
(吐槽一下力扣官方的网络运维,怎么最近一直被攻击,包括我写这篇题解的时候,网页都打不开了……)
力扣双周赛
这道题利用简单的数学知识即可进行解题,我们将“键入”与“指向”用时分开计算,“键入”用时即为给出字符串的长度。对于“指向”用时,这里涉及了一个贪心策略,即:我们每次都要取得最小的移动路径。我们的“指针”从 a 开始,只可能顺时针或逆时针进行移动,而我们需要在这两种选择中获得最小值,最后加上最初的“键入”值,便可以得到答案。
class Solution {
public int minTimeToType(String word) {
//shuzi为“键入值”
int shuzi = word.length();
//index为“指针”
int index = 1;
int answer = 0;
for(int i = 0;i < word.length();i++){
char s = word.charAt(i);
int num = (int)(s-'a')+1;
answer = answer + findMin(index,num);
index = num;
}
return answer+shuzi;
}
//分开讨论,findMin函数用于寻找最短移动路径
public int findMin(int begin,int end){
//对指针和目标位置的不同情况进行不同处理。
if(begin > end){
return Math.min(begin-end,26-begin+end);
}
else{
return Math.min(end-begin,26-end+begin);
}
}
}
//如果对自己写的东西不能很好的清晰理解,建议分成多个模块。笔者在对移动路径分析时,踩了坑。
这一题笔者在比赛过程中并未进行解答。在后期也没有想出个所以然,但是在查看题解时恍然大悟。
- 偶数个负数是可以全部清除的。
- 奇数个负数将最小的减去即可。
那么这题很容易解答(前提是你的思路正确)
class Solution {
public long maxMatrixSum(int[][] matrix) {
long res = 0;
int neg = 0, min = Integer.MAX_VALUE;
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[0].length; j++){
if(matrix[i][j] < 0) neg++;
min = Math.min(min, Math.abs(matrix[i][j]));
res += Math.abs(matrix[i][j]);
}
}
return (neg & 1) == 0 ? res : res - min * 2;
}
}
这一题很容易可以看出使用Floyd或者Dijkstra算法进行求解,可惜笔者忘记了这两种解法。
//Dijkstra
class Solution {
public int countPaths(int n,int[][] times) {
final int INF = Integer.MAX_VALUE;
List<int[]>[] g = new List[n];
for (int i = 0; i < n; ++i) {
g[i] = new ArrayList<int[]>();
}
for (int[] t : times) {
int x = t[0] , y = t[1];
g[x].add(new int[]{y, t[2]});
g[y].add(new int[]{x, t[2]});
}
int mod=1000000007;
int[][] dist = new int[n][2];
for (int i = 0; i < n; i++) {
dist[i][0] = INF;
}
dist[0][0] = 0;
dist[0][1] = 1;
int ans = 0;
PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
pq.offer(new int[]{0, 0});
while (!pq.isEmpty()) {
int[] p = pq.poll();
int time = p[0], x = p[1];
if (dist[x][0] < time) {
continue;
}
for (int[] e : g[x]) {
int y = e[0], d = dist[x][0] + e[1];
if (d == dist[y][0]) {
dist[y][1]+=dist[x][1];
dist[y][1]%=mod;
}
if (d < dist[y][0]) {
dist[y][0] = d;
pq.offer(new int[]{d, y});
dist[y][1]=dist[x][1];
}
}
}
return dist[n-1][1];
}
}
笔者实力有限,最后一题不做题解。
力扣周赛
这一题只需记录一个数组中的最大及最小值,随后对其使用辗转相除法即可求解。
class Solution {
public int findGCD(int[] nums) {
int min = nums[0];
int max = nums[0];
for(int i = 1;i < nums.length;i++){
if(nums[i] > max) max = nums[i];
if(nums[i] < min) min = nums[i];
}
int answer = max % min;
while(answer != 0){
max = min;
min = answer;
answer = max % min;
}
return min;
}
}
相应的,这题我们可以分为两部分来做。
(哈希+递归)
-
得到二进制字符。
利用递归得到不同的二进制字符。
-
与已有的二进制字符进行比较。
利用链表的contains()方法。
当出现与已有二进制字符不同的二进制字符时,利用flag标志,停止递归,返回相应得二进制字符。
class Solution {
String cmp = "";
String answer = "";
int flag = 0;
public String findDifferentBinaryString(String[] nums) {
int n = nums.length;
List<String> data= new ArrayList<String>();
for(int i = 0;i < n;i++){
data.add(nums[i]);
}
dfs(0,n,data);
return answer;
}
public void dfs(int index,int des,List<String> data){
if(flag == 1) return;
if(index == des){
if(!(data.contains(cmp))){
answer = cmp;
flag = 1;
}
return;
}
for(int i = 0;i < 2;i++){
cmp = cmp + i;
dfs(index+1,des,data);
cmp = cmp.substring(0,cmp.length()-1);
}
}
}
笔者代码写的不够简洁,清晰,仅供参考。
笔者实力有限,最后两题不做解答
总结
从两场可以看出,笔者对数据结构及算法的知识有相应的了解,但在解决具体问题和熟练度上均有待提高。
尤其对于图相关的四种算法应加强相关练习。