419 棋盘上的舰队
给你一个大小为 m x n 的矩阵 board 表示棋盘,其中,每个单元格可以是一艘战舰 ‘X’ 或者是一个空位 ‘.’ ,返回在棋盘 board 上放置的 舰队 的数量。
舰队 只能水平或者垂直放置在 board 上。换句话说,舰队只能按 1 x k(1 行,k 列)或 k x 1(k 行,1 列)的形状放置,其中 k 可以是任意大小。两个舰队之间至少有一个水平或垂直的空格分隔 (即没有相邻的舰队)。
思路:舰队:一行or一列,两个舰队之间至少有一个水平或垂直的空格分隔 (即没有相邻的舰队)。这个规则来遍历整个数组并进行计数,计数的原则是只记开头的or结尾的X。起始位置左和上都没有’X’并注意数组越界问题。
class Solution {
public:
int countBattleships(vector<vector<char>>& board) {
int num = 0 , m = board.size() , n = board[0].size();
for(int i = 0 ; i < m ; i++){
//横向左没有[i][j-1] num++,纵向判断上下,上没有[i-1][j]num++ 只判断起点位置
for(int j = 0 ; j < n ; j++){
if(board[i][j] == 'X'){
if((i == 0 || board[i-1][j] != 'X' )&& (j == 0 || board[i][j-1] != 'X')){
num++;
}
}
}
}
return num;
}
};
396 旋转函数
给定一个长度为 n 的整数数组 nums 。
假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组,我们定义 nums 的 旋转函数 F 为:
F(k) = 0 * arrk[0] + 1 * arrk[1] + … + (n - 1) * arrk[n - 1]
返回 F(0), F(1), …, F(n-1)中的最大值 。
生成的测试用例让答案符合 32 位 整数。
class Solution {
public:
int maxRotateFunction(vector<int>& nums) {
//暴力解题
int n = nums.size();
int max = INT_MIN;
for(int i = 0 ; i < n ; i++){
int F = 0;
for(int x = 0; x < n - 1 ; x++){
int j = i + x;
if(j >= n){
j -= n;
}
F += nums[j] * (x+1);
}
max > F ? max : max =F;
}
return max;
}
};
时间复杂度 O ( n 2 ) O(n^2) O(n2)超时了,优化F(k)的计算:利用公式F(k) = F(k-1) + sum - n * nums[n-k]来逐步计算后续的F值,其中sum是数组元素的总和。【默】
class Solution {
public:
int maxRotateFunction(vector<int>& nums) {
int max =INT_MIN , n = nums.size() , F = 0 ,sum = 0;
for(int i = 0 ; i < n ; i++){
F += i * nums[i];
sum += nums[i];
}
int maxF = F;
for(int k = 1 ; k < n ; k ++){
F = F + sum - n * nums[n-k];
maxF > F ? maxF : maxF = F;
}
return maxF;
}
};
54 螺旋矩阵
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
真就旋转旋转再旋转
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
int num = n * m;
vector<int> arr(num);
// 定义初始方向,顺时针依次为右、下、左、上
vector<int> direc = {1, 0, 0, 0}; // 右、下、左、上
int i = 0, j = 0;
while(num--) {
int x = n * m - num - 1;
arr[x] = matrix[i][j];
matrix[i][j] = 101; // 标记已经访问过的位置
if (direc[0]) { // 向右
j++;
if (j == n || matrix[i][j] == 101) { // 越界或遇到已访问位置
j--; // 回到上一个合法位置
i++; // 准备向下
direc = {0, 1, 0, 0}; // 转向下
}
} else if (direc[1]) { // 向下
i++;
if (i == m || matrix[i][j] == 101) { // 越界或遇到已访问位置
i--; // 回到上一个合法位置
j--; // 准备向左
direc = {0, 0, 1, 0}; // 转向左
}
} else if (direc[2]) { // 向左
j--;
if (j < 0 || matrix[i][j] == 101) { // 越界或遇到已访问位置
j++; // 回到上一个合法位置
i--; // 准备向上
direc = {0, 0, 0, 1}; // 转向上
}
} else if (direc[3]) { // 向上
i--;
if (i < 0 || matrix[i][j] == 101) { // 越界或遇到已访问位置
i++; // 回到上一个合法位置
j++; // 准备向右
direc = {1, 0, 0, 0}; // 转向右
}
}
}
return arr;
}
};
优化思路:对边界直接重新定义。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector <int> ans;
if(matrix.empty()) return ans; //若数组为空,直接返回答案
int u = 0; //赋值上下左右边界
int d = matrix.size() - 1;
int l = 0;
int r = matrix[0].size() - 1;
while(true)
{
for(int i = l; i <= r; ++i) ans.push_back(matrix[u][i]); //向右移动直到最右
if(++ u > d) break; //重新设定上边界,若上边界大于下边界,则遍历遍历完成,下同
for(int i = u; i <= d; ++i) ans.push_back(matrix[i][r]); //向下
if(-- r < l) break; //重新设定有边界
for(int i = r; i >= l; --i) ans.push_back(matrix[d][i]); //向左
if(-- d < u) break; //重新设定下边界
for(int i = d; i >= u; --i) ans.push_back(matrix[i][l]); //向上
if(++ l > r) break; //重新设定左边界
}
return ans;
}
};
作者:YouLookDeliciousC
链接:https://leetcode.cn/problems/spiral-matrix/solutions/7155/cxiang-xi-ti-jie-by-youlookdeliciousc-3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
59 螺旋数组Ⅱ
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
//direction另一种版本
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> ans(n,vector<int>(n , 0));
vector<vector<int>> directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int i = 0 , j = 0 , num = n*n , directionIndex = 0;
for(int x = 1 ; x <= num ; x++){
ans[i][j] = x;
// 计算下一个位置
int nextI = i + directions[directionIndex][0];
int nextJ = j + directions[directionIndex][1];
// 检查是否越界或已经访问过
if (nextI < 0 || nextI >= n || nextJ < 0 || nextJ >= n || ans[nextI][nextJ] != 0) {
// 变更方向
directionIndex = (directionIndex + 1) % 4;
nextI = i + directions[directionIndex][0];
nextJ = j + directions[directionIndex][1];
}
i = nextI;
j = nextJ;
}
return ans;
}
};
按照54题的优化题解,重新写了遍。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> ans(n,vector<int>(n , 0));
int num = 1 , l = 0 , r = n-1 , d = n-1 , u = 0;
while(num <= n*n){
for(int i = l ; i <= r ; i++){ans[u][i] = num++;}
if(++u > d) break;//变上界
for(int i = u ; i <= d ; i++){ans[i][r] = num++;}
if(--r < l) break;//变右界
for(int i = r ; i >= l ; i--){ans[d][i] = num++;}
if(--d < u) break;//变下界
for(int i = d ; i >= u ; i--){ans[i][l] = num++;}
if(++l > r) break;//变左界
}
return ans;
}
};