7.11 数组中等 419 396 54 59

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;
    }
    
};
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值