寒假CS每日打卡 Feb.3rd


算法部分

1.Acwing 入门组每日一题
题目:献给阿尔吉侬的花束
阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。
今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。迷宫用一个 R×C 的字符矩阵来表示。字符 S 表示阿尔吉侬所在的位置,字符 E 表示奶酪所在的位置,字符 # 表示墙壁,字符 . 表示可以通行。阿尔吉侬在 1 个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。

输入格式
第一行是一个正整数 T,表示一共有 T 组数据。
每一组数据的第一行包含了两个用空格分开的正整数 R 和 C,表示地图是一个 R×C 的矩阵。接下来的 R 行描述了地图的具体内容,每一行包含了 C 个字符。字符含义如题目描述中所述。保证有且仅有一个 S 和 E。

输出格式
对于每一组数据,输出阿尔吉侬吃到奶酪的最少单位时间。
若阿尔吉侬无法吃到奶酪,则输出“oop!”(只输出引号里面的内容,不输出引号)。每组数据的输出结果占一行。

数据范围
1<T≤10,
2≤R,C≤200
输入样例:
3
3 4
.S…
###.
…E.
3 4
.S…
.E…

3 4
.S…

…E.
输出样例:
5
1
oop!

题解:
  经典的bfs做法,可以使用一个pair来表示二维坐标。利用dist存储每个点距离起点的距离,还可以利用dist数组来判断是否走过该点了,因为一旦走过某个点,其dist值就不为0 。
代码:

#include <iostream>
#include <queue>
#include <cstring>

#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;

const int MAXN = 210;
char g[MAXN][MAXN];
int dist[MAXN][MAXN];
int r, c, fx[4][2] = {
    
    {
    
    0, 1}, {
    
    0, -1}, {
    
    1, 0}, {
    
    -1, 0}};
typedef pair<int, int> PII;

void bfs(int a, int b){
    
    
    memset(dist, 0, sizeof(dist));
	queue<PII> Q;
	PII cur;
	
	Q.push({
    
    a, b});
	dist[a][b] = 0;
	
	while(!Q.empty()){
    
    
		//取得队首元素
		cur = Q.front();
		Q.pop();
		//从上下左右四个方向拓展
		for(int i = 0; i < 4; i ++){
    
    
			int nxtr = cur.first + fx[i][0];
			int nxtc = cur.second + fx[i][1];
			if(nxtr >=0 && nxtr < r && nxtc >= 0 && nxtc < c && !dist[nxtr][nxtc] && g[nxtr][nxtc] != '#'){
    
    
				//更新dist数组
			    dist[nxtr][nxtc] = dist[cur.first][cur.second] + 1;
			    //遇到终点
				if(g[nxtr][nxtc] == 'E'){
    
    
					cout << dist[nxtr][nxtc] << endl;
					return ;
				}
				//新节点入队
				Q.push({
    
    nxtr, nxtc});
			}
		}
	}
	cout << "oop!" << endl;
}

int main(){
    
    
	int n;
	
	cin >> n;	
	while(n --){
    
    
		int a, b;
		cin >> r >> c;
		for(int i = 0; i < r; i ++){
    
    
			cin >> g[i];
			for(int j = 0; j < c; j ++)
				if(g[i][j] == 'S')
					a = i, b = j;
		}
		bfs(a, b);
	}
	return 0;
}

2.Acwing 提高组每日一题
题目:糖果传递
  暂时还没搞明白,明天先尝试这题的基础版:均分纸牌

3.LeetCode 每日一题
题目:滑动窗口中位数
  挺难的,还未做出来。

4.长度最小的子数组
题目:
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

题解:
  考察的知识点为双指针,当区间和大于s,则缩小区间,否则扩大区间,在移动区间的过程中维护答案即可。
代码:

扫描二维码关注公众号,回复: 12472228 查看本文章
class Solution {
    
    
public:
    int minSubArrayLen(int s, vector<int>& nums) {
    
    
        int le = 0, ri = 0, ans = INT_MAX, tmp = 0;

        while(ri < nums.size()){
    
    
            tmp += nums[ri];
            //区间和大于s,需要缩小区间
            while(tmp >= s){
    
    
                ans = min(ans, ri - le + 1);
                tmp -= nums[le ++];
            }
            //区间和已经小于s,需要扩大区间
            ++ ri;
        }
        return ans == INT_MAX ? 0 : ans;
    }
};

5.春招冲刺-括号生成
题目:
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:

输入:n = 1
输出:["()"]

提示:
1 <= n <= 8
题解:
  dfs回溯,和摆放八皇后问题类似,注意剪枝的条件 1、先放置 “ ) ” , 2、剩余全部都用来摆放同一种括号也不能与另外一种括号配对。我们可以使用 k 来记录左右括号的匹配情况。
代码:

class Solution {
    
    
public:
    vector<string> generateParenthesis(int n) {
    
    
        vector<string> ans;
        string tmp(2 * n, 0);
        dfs(ans, tmp, 0, 0, 2 * n);
        return ans;
    }
	//k为括号的配对情况 level对要防止字符的位置 size为最终字符串的大小
    void dfs(vector<string> &ans, string &tmp, int k, int level, const int size){
    
    
    	//先出现 右括号 或者 剩余的字符不能与已有字符串匹配
        if(size - level < abs(k) || k < 0)
            return ;
         //是一个可行解
        if(level == size){
    
    
            ans.push_back(tmp);
            return ;
        }
        //先放左括号 k + 1
        tmp[level] = '(';
        dfs(ans, tmp, k + 1, level + 1, size);
        //放右括号 k - 1
        tmp[level] = ')';
        dfs(ans, tmp, k - 1, level + 1, size);
    }
};

6.春招冲刺-数组组成最大数
题目:
给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。
示例 1:
输入: [10,1,2]
输出: 2110
示例 2:
输入: [3,30,34,5,9]
输出: 9534330

题解:
  考察排序,理解题意后发现,只需要把字典序大的排在前面就行了,但是如果两个字符串长度不一样,就需要比较 长字符串的下一个字符 和 长字符串的第一个字符,因为只有这两种排列方式,见下图。还需要预处理一下输入,输入比较蛋疼,要将输入根据 " , " 转换为string类型的数组。
在这里插入图片描述

代码:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

vector<string> arr;

int main(){
    
    
    string a, s1, s2;
    int pre = 1, cur = 1;

    cin >> a;   
    //处理输入
    while(cur < a.length()){
    
    
        if(a[cur] == ',' || cur == a.length() - 1){
    
    
            arr.push_back(a.substr(pre, cur - pre));
            pre = cur + 1;
        }
        ++ cur;
    }
	//使用c++匿名函数排序
    sort(arr.begin(), arr.end(), [](const string &a, const string &b){
    
    
        for(int i = 0; i < a.length() && i < b.length(); i++){
    
    
            if(a[i] != b[i])
                return a[i] > b[i];
        }
        //两个字符串公共部分都相同
        if(a.length() < b.length())
            return b[0] > b[a.length()];
        else
            return a[0] < a[b.length()];
    });

    string ans;
    for(string &s : arr)
        ans += s;
    cout << ans << endl;
    return 0;
}

7.闫氏dp分析法
  今天看了,觉得一般,dp问题还是要多练,有四道基础dp练习题,大家可以做一下。
01背包问题
完全背包问题
最长公共子序列
石子合并
本人以上四道ac代码合集


书籍部分

MYSQL必知必会 第 13 章 ✔


PS.

  1. 做一下最长公共子串的dp题
  2. 做一下均分纸牌题
  3. 继续做字节跳动的春招冲刺题
  4. 有空看一下markdown

猜你喜欢

转载自blog.csdn.net/Raymond_YP/article/details/113621272
3rd