第一题:转置矩阵

问题:

给定一个矩阵 A, 返回 A 的转置矩阵。

矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。

示例 1:

输入:[[1,2,3],[4,5,6],[7,8,9]]
输出:[[1,4,7],[2,5,8],[3,6,9]]

示例 2:

输入:[[1,2,3],[4,5,6]]
输出:[[1,4],[2,5],[3,6]]

提示:

  1. 1 <= A.length <= 1000
  2. 1 <= A[0].length <= 1000

链接:https://leetcode-cn.com/contest/weekly-contest-92/problems/transpose-matrix/

分析:

行列互换即可

AC Code:

 class Solution {
public:
vector<vector<int>> transpose(vector<vector<int>>& A) {
vector<vector<int>> ret;
vector<int> tmp;
if (A.size() == )
{
return A;
}
int m = A.size();//行
int n = A[].size();//列
for (int j = ; j < n; j++)
{
tmp.clear();
for (int i = ; i < m; i++)
{
tmp.emplace_back(A[i][j]);
}
ret.emplace_back(tmp);
}
return ret;
}
};

其他:

用时最短code(16/28):

 class Solution {
public:
vector<vector<int>> transpose(vector<vector<int>>& A) {
int rows = A.size();
int lines = A[].size(); vector<vector<int>> ans; for(int i = ; i < lines; i++)
{
vector<int> temp;
ans.push_back(temp);
}
for(int i = ; i < rows; i++)
{
for(int j = ; j < lines; j++)
{
ans[j].push_back(A[i][j]);
}
}
return ans;
}
};

第二题:具有所有最深结点的最小子树

问题:

给定一个根为 root 的二叉树,每个结点的深度是它到根的最短距离。

如果一个结点在整个树的任意结点之间具有最大的深度,则该结点是最深的

一个结点的子树是该结点加上它的所有后代的集合。

返回能满足“以该结点为根的子树中包含所有最深的结点”这一条件的具有最大深度的结点。

示例:

输入:[3,5,1,6,2,0,8,null,null,7,4]
输出:[2,7,4]
解释:

我们返回值为 2 的结点,在图中用黄色标记。
在图中用蓝色标记的是树的最深的结点。
输入 "[3, 5, 1, 6, 2, 0, 8, null, null, 7, 4]" 是对给定的树的序列化表述。
输出 "[2, 7, 4]" 是对根结点的值为 2 的子树的序列化表述。
输入和输出都具有 TreeNode 类型。

提示:

  • 树中结点的数量介于 1 和 500 之间。
  • 每个结点的值都是独一无二的。

链接:https://leetcode-cn.com/contest/weekly-contest-92/problems/smallest-subtree-with-all-the-deepest-nodes/

分析:

周赛91中有一个类似的问题,按照同样做法对每个节点进行编码,根节点是0b1,下一次分别是0b10,0b11,然后将得到的数据最后一个即为最底层叶子,根据“宽度”能得到最底层所有叶子,找到公共祖先即为所求节点。

AC Code:

 /**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
//包含该节点的所有子树,最大公共部分就是
//包含该节点的所有子树,最大公共部分就是
TreeNode* subtreeWithAllDeepest(TreeNode* root) {
map<uint64_t, TreeNode*> data;
TreeNode* ret = NULL;
TreeNode tmp();
data = DealTreeNode(root, );
map<uint64_t, TreeNode*>::iterator it;
it = data.end();
it--;
int targetvalue = (*it).first;
int length = GetBLength(targetvalue);
//uint64_t target = 0xFFFFFFFF; set<uint64_t> sets;
for (map<uint64_t, TreeNode*>::reverse_iterator rit = data.rbegin(); rit != data.rend(); rit++)
{
if (GetBLength((*rit).first) == length)
{
sets.insert((*rit).first);
//target = !(target ^ (*rit).first);
}
else
{
break;
} }
//到这里1知道了层次,2得到了最底层一排数据,但是1000如何确认是10的后代还是1的后代呢?
//向上找共同唯一祖先 while (sets.size()>)
{
sets = GetUper(sets);
}
int finalcode = *(sets.begin());
it = data.find(finalcode);
ret = (*it).second;
return ret;
}
set<uint64_t> GetUper(set<uint64_t> setdata)
{
std::set<uint64_t> ret;
for (set<uint64_t>::iterator it = setdata.begin(); it != setdata.end(); it++)
{
ret.insert((*it) / );
}
return ret;
}
int GetBLength(int data)
{
int ret = ;
while (data)
{
ret++;
data /= ;
}
return ret;
}
map<uint64_t, TreeNode*> DealTreeNode(TreeNode* root, int level)
{
map<uint64_t, TreeNode*> ret;
map<uint64_t, TreeNode*> left, right;
//TreeNode tmp(0);
TreeNode* tmp = NULL;
if (root == nullptr)
{
return ret;
}
tmp = root;
ret.insert(make_pair(level, tmp));
left = DealTreeNode(root->left, level * );
right = DealTreeNode(root->right, level * + );
for (map<uint64_t, TreeNode*>::iterator it = left.begin(); it != left.end(); it++)
{
ret.insert(*it);
}
for (map<uint64_t, TreeNode*>::iterator it = right.begin(); it != right.end(); it++)
{
ret.insert(*it);
}
return ret;
} };

其他:

用时最短code(4/8):

 /**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
int doit(TreeNode* root)
{
int tmp1,tmp2;
if (root==NULL) return ;
tmp1=doit(root->left);
tmp2=doit(root->right);
if (tmp1>tmp2) return tmp1+;
else return tmp2+;
} TreeNode* doit2(TreeNode* root,int dep)
{
if (root==NULL) return NULL;
if (dep==) return root;
TreeNode* tmp1=doit2(root->left,dep-);
TreeNode* tmp2=doit2(root->right,dep-);
if (tmp1==NULL) return tmp2;
else if (tmp2==NULL) return tmp1;
else return root;
} class Solution {
public:
TreeNode* subtreeWithAllDeepest(TreeNode* root) {
int tmp=doit(root);
return doit2(root,tmp);
}
};

1.doit 得到层数

2.left  right中如果都含有最低一层,返回root,否则返回含有最低一层的一个

第三题:回文素数

问题:

求出大于或等于 N 的最小回文素数。

回顾一下,如果一个数大于 1,且其因数只有 1 和它自身,那么这个数是素数

例如,2,3,5,7,11 以及 13 是素数。

回顾一下,如果一个数从左往右读与从右往左读是一样的,那么这个数是回文数。

例如,12321 是回文数。

示例 1:

输入:6
输出:7

示例 2:

输入:8
输出:11

示例 3:

输入:13
输出:101

提示:

  • 1 <= N <= 10^8
  • 答案肯定存在,且小于 2 * 10^8

链接: https://leetcode-cn.com/contest/weekly-contest-92/problems/prime-palindrome/

分析:

1.回文数比素数更稀疏

2.根据回文数特定,只需要知道一半就能构造出数据。

AC Code:

 class Solution {
public:
int primePalindrome(int N) {
if (N <= )
{
return ;
}
if (N == )
{
return ;
}
if (N <= )
{
return ;
}
if (N <= )
{
return ;
}
if (N <= )
{
return ;
}
if (N <= )
{
return ;
} //先得到下一个回文数
int ret = N - ;
while (true)
{
ret = GetNextPalindrome(ret);
//判断是否是素数,如果是,则返回,否则找到下一个回文数继续判断
if (isPrime(ret) == )
{
return ret;
}
} } int GetNextPalindrome(int data)
{
//100以内的数字已经特殊考虑过,不存在差值1的两个回文数
//首先得到长度,如果是奇数,取前一半+中间值构造,如果是偶数,取前一半构造
int tmpdata=data;
int length = ;
while (tmpdata)
{
tmpdata /= ;
length++;
}
//到这里得到数据长度,根据奇偶判断
if (length % == )
{
//偶数长度
int highhalf = data / (pow(, length / )); //得到前一半
int lowhalf = data % (int)(pow(, length / )); //低一半
int tmphigh = GetPallindrom(highhalf);
if (tmphigh > lowhalf)
{
//只需要将高一般构建结果即可
return data + (tmphigh - lowhalf);
}
else
{
highhalf += ;
int tmplength = ;
tmpdata = highhalf;
while (tmpdata)
{
tmpdata /= ;
tmplength++;
}
if (tmplength == length / )
{
//没产生进位
return highhalf*pow(, tmplength) + GetPallindrom(highhalf);
}
else
{
//返回奇数个的10X01
return highhalf*pow(, tmplength-) + GetPallindrom(highhalf);
} }
}
else
{
//奇数长度中间+1即可,如果原来是9,变为10XX01
int highhalf = data / (int)(pow(, length / ));
int mid = highhalf % ;
highhalf /= ;
int lowhalf = data % (int)(pow(, length / ));
int tmphighhalf = GetPallindrom(highhalf); //不需要动到中间位置数组
if (tmphighhalf > lowhalf)
{
return data + (tmphighhalf - lowhalf);
} //需要更新中间数字
if (mid < )
{
return (highhalf * + mid + )*pow(, length / ) + tmphighhalf;
}
else
{
//高一半+1不进位,只需要高一半+1,该位变0即可,比如191 -> 202
//如果高位+1后需要进位,如99X,则需要变为1001,即最小的高一位
mid = ;
highhalf += ;
tmphighhalf = GetPallindrom(highhalf);
int tmplength = ;
tmpdata = highhalf;
while (tmpdata)
{
tmpdata /= ;
tmplength++;
}
if (tmplength == length / )
{
//没产生进位
return (highhalf * + mid)*pow(, length / ) + tmphighhalf;
}
else
{
//产生了进位 比如999应该变为1001
return highhalf*pow(, tmplength) + tmphighhalf;
}
} }
}
int isPrime(int data)
{
if (data == || data == )
{
return ;
}
for (int i = ; i*i <= data; i++)
{
if (data%i == )
{
return ;
}
}
return ;
}
int GetPallindrom(int data)
{
int ret = ;
while (data>)
{
ret = ret * + data % ;
data = data / ;
}
//cout << "debug:" << data << " -> " << ret << endl;;
return ret;
} };

其他:

用时最短code(0/12)

 class Solution {
public:
int primePalindrome(int N) {
if (N<=) return ;
string s = to_string(N);
int base = stoi(s.substr(, (s.size()+)/));
int flag = (s.size()%==?:);
while (true) {
int n = base;
for (int k = (flag==?n/:n); k>; k/=) n = n*+k%;
if (n>=N && isPrime(n))
return n;
base ++;
if ((base== || base== || base== || base==)) {
if (flag==) base /= ;
flag = (flag==?:);
}
}
return ;
} bool isPrime(int n) {
if (n==) return true;
if (n%==) return false;
for (int i=; i*i<=n; i+=) {
if (n%i==)
return false;
}
return true;
}
};

第四题:获取所有钥匙的最短路径

问题:

  • 用户通过次数0
  • 用户尝试次数4
  • 通过次数0
  • 提交次数6
  • 题目难度Hard

给定一个二维网格 grid。 "." 代表一个空房间, "#" 代表一堵墙, "@" 是起点,("a""b", ...)代表钥匙,("A""B", ...)代表锁。

我们从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间。我们不能在网格外面行走,也无法穿过一堵墙。如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。

假设 K 为钥匙/锁的个数,且满足 1 <= K <= 6,字母表中的前 K 个字母在网格中都有自己对应的一个小写和一个大写字母。换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁。另外,代表钥匙和锁的字母互为大小写并按字母顺序排列。

返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。

示例 1:

输入:["@.a.#","###.#","b.A.B"]
输出:8

示例 2:

输入:["@..aA","..B#.","....b"]
输出:6

提示:

  1. 1 <= grid.length <= 30
  2. 1 <= grid[0].length <= 30
  3. grid[i][j] 只含有 '.''#''@''a'-'f' 以及 'A'-'F'
  4. 钥匙的数目范围是 [1, 6],每个钥匙都对应一个不同的字母,正好打开一个对应的锁。

链接:https://leetcode-cn.com/contest/weekly-contest-92/problems/shortest-path-to-get-all-keys/

分析:

最开始做法是记录每一条路径,从起点开始,得到接下来可能的下一步,如果是#不可达,如果是门但是没有对应钥匙,不可达,如果已经存储在路径中不可达,如果是.或者钥匙,或者是门但有对应钥匙,视为道路,

并存储到路径中。如果拿到了一把新钥匙,清空已经记录的路径,因为原来不可达的位置也许现在能够到达了,运行走回头路。可惜超时了。折腾一周都没搞出来,参考https://blog.csdn.net/yanglingwell/article/details/80984968。

感觉比较巧妙的地方有:

1,同一起点的接下来不同走法采用同一个地图,同时走过的路都设为#,不需要记录就可以避免回头。

2,BFS中当前位置存储在一个队列中,通过{-1,-1}来隔离下一步能够到达的位置。

AC Code:

 pair<int, int> BFS(const vector<string>& grid, int x, int y, string keysearched, char key, int& len)
{
if (x< || x>=grid.size() || y< || y>=grid[].size())
{
return{-,-};
}
vector<string> localgrid(grid);
localgrid[x][y] = '#';
queue<pair<int, int>> que;
que.push({ x, y });
que.push({ -, - });
int directions[][] = { { , }, { , }, { , - }, { -, } };
while (!que.empty())
{
int curx = que.front().first;
int cury = que.front().second; que.pop();
if (curx == - && que.empty())
{
continue;
}
else if (cury == - && !que.empty())
{
que.push({ -, - });
++len;
continue;
} for (int i = ; i < ; i++)
{
int tx = curx + directions[i][];
int ty = cury + directions[i][];
if (tx < || tx >= grid.size() || ty < || ty >= grid[].size())
{
continue;
}
if (localgrid[tx][ty] == '#')
{
continue;
}
if (isupper(localgrid[tx][ty]) && keysearched.find(tolower(localgrid[tx][ty])) == keysearched.npos)
{
continue;
} //找到了目标key
if (localgrid[tx][ty]==key && keysearched.find(tolower(localgrid[tx][ty])) == keysearched.npos)
{
return{ tx, ty };
} localgrid[tx][ty] = '#';
que.push({ tx, ty });
}
}
return{ -, - };
}
//返回
int DFS(const vector<string>& grid, int x, int y, string keysearched, string keysearching)
{
//起点越界
if (x< || x>=grid.size() || y< || y>=grid[].size())
{
return -;
}
if (keysearching.empty())
{
return ;
} int ans = -;
//逐个找key
for (int i = ; i < keysearching.size(); i++)
{
int nextLen = ;
pair<int,int> nextpos = BFS(grid, x, y, keysearched, keysearching[i],nextLen);
if (nextpos.first == -)
{
continue;
}
string tmpkeysearched(keysearched);
string tmpkeysearching(keysearching);
tmpkeysearched.push_back(grid[nextpos.first][nextpos.second]);
tmpkeysearching.erase(keysearching.find(grid[nextpos.first][nextpos.second]), ); //find不是在新的string里面?
//tmpkeysearching.erase(tmpkeysearching.find(grid[nextpos.first][nextpos.second]), 1); //find不是在新的string里面? int ret = DFS(grid, nextpos.first, nextpos.second, tmpkeysearched, tmpkeysearching);
if (ret == -)
{
continue;
}
if (ans == - || ans > ret + nextLen)
{
ans = ret + nextLen;
} }
return ans;
}
//找到起始点坐标,各个钥匙坐标
//通过 二维数组jil
//https://blog.csdn.net/yanglingwell/article/details/80984968
int shortestPathAllKeys(vector<string>& grid) {
//参考网络编写code
//首先得到起点位置
int location_x, location_y=-;
string keys;
for (int i = ; i < grid.size(); i++)
{
for (int j = ; j < grid[i].size(); j++)
{
if (grid[i][j] == '@')
{
location_x = i;
location_y = j;
}
if (islower(grid[i][j]))
{
keys.push_back(grid[i][j]);
}
} } return DFS(grid, location_x, location_y, "", keys); }

其他:

用时最短code(8/272)

 int t[][][ << ];
int dr[] = {-, , , }, dc[] = {, , , -};
class Solution { public:
vector<string> g;
int m, n;
int shortestPathAllKeys(vector<string>& grid) {
g = grid;
m = grid.size();
if(m == ) return -;
n = grid[].size();
if (n == ) return -;
for(int i = ; i < m; i++){
for(int j = ; j < n; j++){
if(grid[i][j] == '@') return go(i, j);
}
}
return -;
}
int go(int r, int c){
int all = ;
for(int i = ; i < m; i++){
for(int j = ; j < n; j++){
if('a' <= g[i][j] && g[i][j] <= 'z')
all |= ( <<(g[i][j] - 'a'));
}
}
memset(t, 0xff, sizeof(t));
t[r][c][] = ;
deque<int> que;
que.push_back((r << ) + (c << ) + );
while(!que.empty()){
int key = que.front();
que.pop_front();
r = key >> ;
c = (key >> ) & 0x3f;
int k = key & 0x3f;
for(int i = ; i < ; i++){
int r1 = r + dr[i];
int c1 = c + dc[i];
if(r1 < || c1 < || r1 >= m || c1 >=n) continue;
char ch = g[r1][c1];
if(ch == '#') continue;
if('A' <= ch && ch <='Z'){
int x = << (ch - 'A');
if( !(x&k)) continue;
}
int k1 = k;
if('a' <=ch && ch <='z'){
k1 |= ( <<(ch - 'a'));
}
if (t[r1][c1][k1] < ){
t[r1][c1][k1] = t[r][c][k] + ;
if(k1 == all) return t[r1][c1][k1];
que.push_back((r1 << ) + (c1 << ) + k1);
}
}
}
return -; }
};

LeetCode之Weekly Contest 92的更多相关文章

  1. LeetCode之Weekly Contest 93

    第一题:二进制间距 问题: 给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离. 如果没有两个连续的 1,返回 0 . 示例 1: 输入:22 输出:2 解释: 22 的 ...

  2. LeetCode之Weekly Contest 102

    第一题:905. 按奇偶校验排序数组 问题: 给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素. 你可以返回满足此条件的任何数组作为答案. 示例: 输入: ...

  3. LeetCode之Weekly Contest 91

    第一题:柠檬水找零 问题: 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10  ...

  4. LeetCode之Weekly Contest 90

    LeetCode第90场周赛记录 第一题:亲密字符串 问题: 给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true :否则返回  ...

  5. LeetCode之Weekly Contest 101

    前一段时间比较忙,而且做这个对于我来说挺耗时间的,已经间隔了几期的没做总结了,后面有机会补齐.而且本来做这个的目的就是为了防止长时间不做把编程拉下,不在追求独立作出所有题了.以后完赛后稍微尝试下,做不 ...

  6. LeetCode Weekly Contest 8

    LeetCode Weekly Contest 8 415. Add Strings User Accepted: 765 User Tried: 822 Total Accepted: 789 To ...

  7. Leetcode Weekly Contest 86

    Weekly Contest 86 A:840. 矩阵中的幻方 3 x 3 的幻方是一个填充有从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等. 给定一个 ...

  8. leetcode weekly contest 43

    leetcode weekly contest 43 leetcode649. Dota2 Senate leetcode649.Dota2 Senate 思路: 模拟规则round by round ...

  9. LeetCode Weekly Contest 23

    LeetCode Weekly Contest 23 1. Reverse String II Given a string and an integer k, you need to reverse ...

随机推荐

  1. 极客学院年VIP卡原价260的F码,200出售

    F码是中国最大的IT职业在线教育平台——极客学院推出的VIP时间兑换码,凭此可在极客学院官网兑换年VIP,畅享平台上所有IT技术课程. 购买请点击 http://www.bejson.com/othe ...

  2. Avito Cool Challenge 2018-B. Farewell Party(思维)

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...

  3. Hive进阶_Hive数据的导入

    使用Load语句执行数据的导入 语法: load data [local] inpath 'filepath' [overwrite] into table tablename [partition ...

  4. 转 MySQL权限管理

    ###sample: #####view all userSELECT user, host from mysql.user;mysql> SELECT user, host from mysq ...

  5. mysql 无法启动 unkown command

    1. https://serverfault.com/questions/490656/mysql-not-starting-error-usr-sbin-mysqld-unknown-option- ...

  6. 038 Count and Say 数数并说

    数数并说序列是一个整数序列,第二项起每一项的值为对前一项的计数,其前五项如下:1.     12.     113.     214.     12115.     1112211 被读作 " ...

  7. 重置 linux系统后要配置的基本组件操作

    1.安装jdk https://www.cnblogs.com/shihaiming/p/5809553.html 2.安装mysql 3.安装tomcat

  8. Ionic开发-搭建开发环境

    1安装node.js 2安装ionic & cordova: 命令行输入:npm install –g cordova ionic 注:-g表示全局安装,也可以进入指定的目录安装,但这里推荐全 ...

  9. winform代码生成器(一)

    (PS  sqlhelper的文件 竟放到 类库里了,第二篇已做了分离,边做边写的 ^_^) 做 Winform  项目时,要拖很多控件,感觉在做重复的事,那就应该用程序来完成,那就自己写一个吧.-- ...

  10. C#高级语法

    委托 委托就是指针函数,委托的定义与类的属性定义类似都必须在类的方法体进行. 委托的定义: class Program { //定义委托:委托不能在方法体内定义. public delegate st ...