C++力扣刷题记录——数组(持续更新)


参考资料:
http://www.cplusplus.com/reference/unordered_map/unordered_map/
C++ Primer

1:高度检查器

学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列。
请你返回能让所有学生以 非递减 高度排列的最小必要移动人数。
在这里插入图片描述
思路:
插入排序+检查几位不同

class Solution {
public:
    int heightChecker(vector<int>& heights) {
        vector<int> heights_copy(heights);
        for(int i=0;i<heights.size();i++)
        {
            //若后面一个元素比其前面一个元素小,
            //则将这两个元素交换位置,
            for(int j = i - 1; j >= 0; j--)
            {
                if(heights[j+1]<heights[j])
                {
                    int x;
                    x=heights[j];
                    heights[j]=heights[j+1];
                    heights[j+1]=x;
                }
            }
        }
        int count=0;
        for(int i=0;i<heights.size();i++)
        {
            if(heights[i]!=heights_copy[i])
            count++;
        }
        return count;
    }
};

在看了解题思路后,差不多就是插入排序+检查 看到了一个

vector<int>  res;
sort(res.begin(), res.end());

解释:
sort(begin, end, cmp),其中begin为指向待sort()的数组的第一个元素的指针,end为指向待sort()的数组的最后一个元素的下一个位置的指针,cmp参数为排序准则,如果没有的话,默认以非降序排序。

2:剑指offer 53 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
在这里插入图片描述
思路;搜索问题:
不缺数字的求和-数组求和=少的数字 OR 二分 OR 下标和数字没对上的那个数

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int sum =0;  
        for(int i=0;i<nums.size();i++)
        {
            sum+=nums[i];
        }
        int sum1 =(0+(int)nums.size())*((int)nums.size()+1)/2-sum;
        return sum1;
    }
};

二分法(在数组的搜索问题中,首先需要想到的就是搜索方法)
在数组的搜索问题中,首先需要想到的就是搜索方法
左子数组的都是下标和数字是一样的,右子数组的下标和数字是不一样的。

class Solution {
public:
    int missingNumber(vector<int>& nums) {
    int n = nums.size();
        int left = 0, right = n - 1;
        while(left < right){
            int mid = (right+left) / 2;
            if(nums[mid] == mid){
                left = mid + 1;
            }else
                right = mid;
        }
        return left == nums[left] ? left + 1 : left;

    }
};

3:350.两个数组的交集 Ⅱ

给定两个数组,编写一个函数来计算它们的交集。
在这里插入图片描述
说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。

思路:哈希表 OR 排序之后两个指针遍历

思路1:
哈希表 在C++ STL中命名为 unordered_map<A,B>;
把短的数组存一编,然后使用长的遍历去找。找到输出,并减少次数。

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        if (nums1.size()>nums2.size())
        	return intersect(nums2,nums1);
        unordered_map<int,int> mymap;
        for(int num:nums1)
        {
            ++mymap[num];
        }

        vector<int> output;
        for(int num:nums2)
        {
            if(mymap[num]!=0)
            {
                output.push_back(num);
                --mymap[num];
            }
        }
        return output;
    }
};

思路二:
先排序,再使用两个指针分别指。小的值移动一个。如果遇到一样大,一起移动。(排序使用sort)使用iterator 来遍历vector .要注意的是iterator 是一个指针哦~vector本质上是一个数组。

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        sort(nums1.begin(),nums1.end());
        sort(nums2.begin(),nums2.end());
        vector <int>::iterator it1,it2;
        it1=nums1.begin();
        it2=nums2.begin();

        vector <int> output;
        while(it1!=nums1.end()&&it2!=nums2.end())
        {
            if(*it1!=*it2)
            {
                *it1<*it2?it1++:it2++;
            }
            else
            {
                output.push_back(*it1);
                it1++;
                it2++;
            }
        }
         return output;

    }
};

4:面试题 16.04 井字游戏

设计一个算法,判断玩家是否赢了井字游戏。输入是一个 N x N 的数组棋盘,由字符" ",“X"和"O"组成,其中字符” "代表一个空位。

以下是井字游戏的规则:

玩家轮流将字符放入空位(" “)中。
第一个玩家总是放字符"O”,且第二个玩家总是放字符"X"。
"X"和"O"只允许放置在空位中,不允许对已放有字符的位置进行填充。
当有N个相同(且非空)的字符填充任何行、列或对角线时,游戏结束,对应该字符的玩家获胜。
当所有位置非空时,也算为游戏结束。
如果游戏结束,玩家不允许再放置字符。
如果游戏存在获胜者,就返回该游戏的获胜者使用的字符(“X"或"O”);如果游戏以平局结束,则返回 “Draw”;如果仍会有行动(游戏未结束),则返回 “Pending”。

思路:分类。有输赢无非就是行、列、对角线有一个是元素非空格的。然后如果没有,判断空否,有空就是Pending,没有就是Draw。(自己写的一直编译不过
vector
可能需要去看下string的访问方式)下面为leetcode上的一个思路类似的答案。另一种求和的方式感觉会存在bug。

class Solution {
public:
    string tictactoe(vector<string>& board) {
        size_t count_x = 0, count_o = 0, len = board.size();
        for (const auto& str : board)
            for (const auto& ch : str) {
                if (ch == 'X') ++count_x;
                else if (ch == 'O') ++count_o;
            }
        if (isWin('X', board, len)) return "X";
        if (isWin('O', board, len)) return "O";
        //是否没下满棋盘
        return count_x + count_o < len * len ? "Pending" : "Draw";
    }
    
    bool isWin(const char& ch, vector<string>& board, const size_t& len) {
        //横向
        for (size_t i = 0; i < len; ++i) {
            for (size_t j = 0; j < len; ++j) {
                if (board[i][j] != ch) break;
                else if(j == len - 1) return true;
            }
        }
        //纵向
        for (size_t j = 0; j < len; ++j) {
            for (size_t i = 0; i < len; ++i) {
                if (board[i][j] != ch) break;
                else if(i == len - 1) return true;
            }
        }
        //正对角线
        bool found = true;
        for (size_t i = 0; i < len; ++i)
            if (board[i][i] != ch) {
                found = false;
                break;
            }
        if (found) return true;
        //逆对角线
        found = true;
        for (size_t i = 0; i < len; ++i)
            if (board[i][len - 1 - i] != ch) {
                found = false;
                break;
            }
        return found;
    }
};

5 大小为K且平均值大于等于阈值的子数组数目

给你一个整数数组 arr 和两个整数 k 和 threshold 。

请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int numOfSubarrays(vector<int>& arr, int k, int threshold) {
        int target = threshold*k;
        int flag =0;
        vector<int>::iterator it;
        if(arr.size()<k)
        {
            return -1;
        }
        for(it=arr.begin();it!=arr.end()-k+1;it++)
        {
            long sum=-target;
            for(int i=0;i<k;i++)
            {
                sum+=*(it+i);
            }
            if (sum >=0)
                ++flag;
        }
        return flag;

    }
};

我的代码在测试用例上没有问题,但是在提交过程中最后一个用例 超出时间限制,要是有人看懂为什么了可以评论一下。
迭代器的取值操作 参考

然后看了别人的思路。
思路:
step1 : 取出前k个数求和,然后减去k*threshold ,如果结果大于0,说明符合要求。
step2 : 指针后移一位,用后移一位的值减去移动之前的第一位的值,再加上上次减法的结果,如果大于0,说明符合要求

整体思路没有除法,只有增量的加减,而且加减数值非常小。

class Solution {
public:
    int numOfSubarrays(vector<int>& arr, int k, int threshold) {
        int sum=0,result=0;
        int sumTarget=k*threshold;
        for(int i=0;i<k;i++)
        {
            sum+=arr[i];
        }
        int adder=sum-sumTarget;
        if(adder>=0)
        {
            result++;
        }
        for(int i=0;i<arr.size()-k;i++)
        {
            adder=adder-arr[i]+arr[i+k];
            if(adder>=0)
                {
                    result++;
                }
        }
            return result;
    }
};

链接:https://leetcode-cn.com/problems/number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold/solution/ci-ti-zui-you-jie-hua-dong-chuang-kou-jia-dong-tai/
来源:力扣(LeetCode)

感觉很妙

6 剑指offer 45.把数组排成最小的数

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。在这里插入图片描述
TIPS:int转string的一些方法。
int i = 100;
方法一:String s1 = i + " ";
方法二:String s2 = String.valueof(i);
方法三(先转换为Integer类型,在调用toString方法)
Intrger i2 = new interger(i);
String s3 = i2.toString();
方法四:String s4 = Integer.toString(i);

[](string& s1, string& s2){return s1 + s2 < s2 + s1;}

一个lambda表达式的写法,重定义了排序的顺序,如果s1+s2<s2+s1认为 s1 < s2
https://www.jianshu.com/p/d686ad9de817

class Solution {
public:
    string minNumber(vector<int>& nums) {
      vector<string>strs;
        string ans;
        for(int i = 0; i < nums.size(); i ++){
            strs.push_back(to_string(nums[i]));
        }
        sort(strs.begin(), strs.end(), [](string& s1, string& s2){return s1 + s2 < s2 + s1;});
        for(int i = 0; i < strs.size(); i ++)
            ans += strs[i];
        return ans;
    }
};

学习一下lamada

7 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值