Day 2 | LeetCode 977.有序数组的平方, LeetCode 209. 长度最小的子数组, LeetCode 59. 螺旋矩阵 II

文章介绍了如何使用双指针策略解决LeetCode中的三个问题:有序数组的平方、长度最小的子数组和螺旋矩阵II,涉及到了数组操作、滚动窗口和边界判断技巧。

LeetCode 977.有序数组的平方

1.从中间开始双指针
class Solution {
public:
    vector<int> result;
    vector<int> sortedSquares(vector<int>& nums) {
        int fast = 0;
        int slow = 0;
        for (; fast < nums.size() && nums[fast] < 0; fast++) {

        }
        //fast指向第一个>=0的下标
        slow = fast - 1; //slow就指向了负数中最大的,平方后最小的下标
        while (slow >= 0 && fast < nums.size()) {
            //从中间分别往左和往右移动指针,将小的数push进result
            int temp = pow(nums[slow], 2) < pow(nums[fast], 2) ? pow(nums[slow--], 2) :  pow(nums[fast++], 2);
            result.push_back(temp);
        }
        //两个while其实只执行一个
        while (slow >= 0) {
            result.push_back(pow(nums[slow--], 2));
        }
        while (fast < nums.size()) {
            result.push_back(pow(nums[fast++], 2));
        }
        
        return result;
    }
};
2.从两边开始双指针
class Solution {
public:

    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result(nums.size(), 0);
        int left = 0; //左右指针
        int right = nums.size() - 1;
        int len = nums.size();
        while (left <= right) {
            int temp = pow(nums[left], 2) > pow(nums[right], 2) ? pow(nums[left++], 2) : pow(nums[right--], 2);
            result[--len] = temp;
       }
       return result;
    }
};

LeetCode 209. 长度最小的子数组

滑动窗口 + 双指针
当窗口内的sum < target, 右指针right++, sum递增,直到sum >= target
当窗口内的sum >= target, 左指针left就一直加,同时sum以此递减,直到窗口内的sum < target
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left = 0;
        int right = 0;
        int sum = 0;
        int minLength = INT_MAX;
        
        for(; right < nums.size(); right++) {
            sum += nums[right]; //sum+= 的操作因该在此处,不能在循环尾部
            while (sum >= target) {
                minLength = min(minLength, right - left + 1);
                sum -= nums[left++];
            }
        }
        //判断数组内是否有解。 有返回minLength, 无返回0
        return minLength == INT_MAX ? 0 : minLength;
    }
};

LeetCode 59. 螺旋矩阵 II

较考验Coding水平和边界判断能力 我跪了🥲
class Solution { 
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int loop = n / 2;
        
        int xStart = 0;
        int yStart = 0;
        int bound = 1;
        int x = 0;
        int y = 0;
        int count = 1; //计数器
        int mid = n / 2; //中间位置
        while (loop--) {
            x = xStart;
            y = yStart;
            for (; y < n - bound; y++) {
                res[x][y] = count++;
            }
            for (; x < n - bound; x++) {
                res[x][y] = count++;
            }
            for (; y > xStart; y--) {
                res[x][y] = count++;
            }
            for (; x > yStart; x--) {
                res[x][y] = count++;
            }
            bound += 1;
            xStart++;
            yStart++;
        }
        if (n % 2 == 1) {
            //奇数矩阵
            res[mid][mid] = count;
        }
        return res;

    }
};
<think>嗯,用户让我用MS SQL Server写LeetCode 550题游戏玩法分析IV。我得先看看题目要求是什么。可能用户是正在准备面试或者刷题,需要解决这个问题。首先,我需要回忆或者查找题目描述。 LeetCode 550的题目通常涉及游戏玩法分析,IV的话可能涉及到连续登录或者某种统计。假设题目是计算在第一天登录后第二天也登录的玩家的比例,或者是类似的比例问题。比如,计算在首次登录后的第二天再次登录的玩家占总玩家的比例,四舍五入到小数点后两位。 接下来,我需要考虑如何用SQL实现这个逻辑。可能的步骤包括: 1. 确定每个玩家的首次登录日期。 2. 检查每个玩家是否存在在首次登录日期后一天再次登录的记录。 3. 统计满足条件的玩家数量,并计算占总玩家数的比例。 首先,每个玩家的首次登录日期可以通过GROUP BY和MIN(event_date)来获取。例如: SELECT player_id, MIN(event_date) AS first_login FROM Activity GROUP BY player_id; 然后,需要将原表Activity与这个首次登录表进行连接,条件是同一玩家,且第二次登录的日期正好是首次登录的第二天。比如: SELECT a.player_id FROM Activity a JOIN first_login f ON a.player_id = f.player_id WHERE a.event_date = DATEADD(day, 1, f.first_login); 这里要注意,可能需要用DISTINCT来避免重复计数,因为一个玩家可能在第二天多次登录,但只算一次。 然后,计算满足条件的玩家数除以总玩家数。总玩家数可以通过COUNT(DISTINCT player_id)从Activity表获取。或者,使用子查询先得到每个玩家的首次登录,再统计总数。 最后,将结果四舍五入到两位小数,并用ROUND函数处理。 可能的完整查询结构: WITH first_login AS ( SELECT player_id, MIN(event_date) AS first_login FROM Activity GROUP BY player_id ), consecutive_login AS ( SELECT DISTINCT a.player_id FROM Activity a JOIN first_login f ON a.player_id = f.player_id WHERE a.event_date = DATEADD(day, 1, f.first_login) ) SELECT ROUND( (SELECT COUNT(*) FROM consecutive_login) * 1.0 / (SELECT COUNT(DISTINCT player_id) FROM Activity), 2 ) AS fraction; 这里需要注意除数是否为0的情况,但题目中可能保证至少有一个玩家,所以不需要处理。另外,使用CTE(公共表表达式)可以提高可读性。测试的时候需要考虑边界情况,比如没有玩家满足条件,或者所有玩家都满足的情况。 用户可能遇到的问题包括:如何计算比例,如何处理日期加减,以及如何避免重复计数。此外,确保使用正确的聚合函数和子查询结构。比如,在计算总玩家数时,可能需要用子查询而不是直接从CTE中取,因为可能有玩家在Activity表中存在但未在first_login中出现,但实际GROUP BY已经覆盖所有玩家,所以不会有问题。 另外,检查日期比较是否正确。例如,DATEADD(day,1,first_login)是否正确生成第二天。有些情况下可能需要使用不同的日期函数,但在SQL Server中DATEADD是正确的。 最后,确保输出为小数点后两位,并且类型转换为浮点数,比如乘以1.0来避免整数除法的问题。例如,COUNT(*) * 1.0 将结果转换为浮点数,再进行除法运算。</think>以下是解决LeetCode 550题“游戏玩法分析IV”的MS SQL Server实现思路及代码: ### 题目理解 **要求**:计算在首次登录后第二天再次登录的玩家占总玩家数的比例,结果保留两位小数。 --- ### 解决步骤 1. **获取首次登录日期** 使用 `MIN(event_date)` 找到每个玩家的首次登录日期。 2. **检查次日登录** 通过连接原始表与首次登录表,筛选出满足 `event_date = 首次登录日期 + 1天` 的记录。 3. **计算比例** 统计符合条件的玩家数,除以总玩家数,并处理四舍五入。 --- ### 完整SQL代码 ```sql WITH -- 步骤1:获取每个玩家的首次登录日期 first_login AS ( SELECT player_id, MIN(event_date) AS first_day FROM Activity GROUP BY player_id ), -- 步骤2:找到在首次登录次日有活动的玩家 consecutive_players AS ( SELECT DISTINCT a.player_id FROM Activity a JOIN first_login f ON a.player_id = f.player_id WHERE a.event_date = DATEADD(day, 1, f.first_day) ) -- 步骤3:计算比例(四舍五入到两位小数) SELECT ROUND( (SELECT COUNT(*) FROM consecutive_players) * 1.0 / (SELECT COUNT(DISTINCT player_id) FROM Activity), 2 ) AS fraction; ``` --- ### 关键点解析 1. **CTE分层处理** 使用公共表表达式(CTE)将问题拆解为两个清晰的子任务,提升可读性。 2. **避免重复计数** `SELECT DISTINCT` 确保同一玩家多次次日登录时只计数一次。 3. **浮点数转换** `COUNT(*) * 1.0` 将整数转换为浮点数,避免除法结果被截断为0。 4. **日期处理** `DATEADD(day, 1, first_day)` 准确计算次日日期。 --- ### 示例数据验证 假设输入表 `Activity` 数据: | player_id | event_date | |-----------|------------| | 1 | 2023-01-01 | | 1 | 2023-01-02 | | 2 | 2023-01-02 | | 3 | 2023-01-03 | | 3 | 2023-01-04 | - **首次登录日期**: `(1→2023-01-01), (22023-01-02), (3→2023-01-03)` - **次日登录玩家**: 仅玩家1在2023-01-02登录(符合条件)。 - **计算结果**: `1/3 ≈ 0.33` --- 通过此方法可高效解决问题,逻辑清晰且符合SQL最佳实践。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值