0207今天是15的一天冲鸭

歧路亡羊是目前的很大敌人,故,统一处理,集中兵力成了我最重要的事情,但凡学习必须专注,否则宁可不学,只有投入和专注才能真正打赢这场仗

疑问:

1.sort函数的[]

优点:

1.从1开始回减,有效控制范围

class Solution {
public:
    bool canAttendMeetings(vectorint>>& intervals) {
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});
        for (int i = 1; i < intervals.size(); ++i) {
            if (intervals[i][0] < intervals[i - 1][1]) {
                return false;
            }
        }
        return true;
    }
};

LC278

这道题最重要的是,终止条件的判别。避免陷入死循环。对mid的计算不能直接(left+right)/2,会导致左右太大时,越界,left+(right-left)/2则是一定不会越界的方法,非常好,值得肯定。

此外题干说尽量少用判别函数,所以判别函数虽然也可以决定是否终止,我们应该选择更好的判别方法

// Forward declaration of isBadVersion API.
bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int left = 0, right = n; //[left, right]
        //用这种一定有界的循环,尽量少使用while 1这种情况,避免死循环超时
        while (left <= right) {
            int mid = left + (right - left) / 2;
            //题干说尽量少使用判断的调用
            if (isBadVersion(mid)) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
};

LC283

双指针法,优点:

指针是一种方法名称,并非必须得要指针,用下标一样作用,要领会精神

swap是在std空间的,可以大胆使用

疑问:

swap能交换什么种类的值

答疑:

大部分类型包括vector都可以直接交换

// swap algorithm example (C++98)
#include      // std::cout
#include     // std::swap
#include        // std::vector

int main () {

  int x=10, y=20;                              // x:10 y:20
  std::swap(x,y);                              // x:20 y:10

  std::vector<int> foo (4,x), bar (6,y);       // foo:4x20 bar:6x10
  std::swap(foo,bar);                          // foo:6x10 bar:4x20

  std::cout << "foo contains:";
  for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

 

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for (int i = 0, j = 0; i < nums.size(); ++i) {
            if (nums[i]) {
                swap(nums[i], nums[j++]);
            }
        }
    }
};

ps:vector的remove函数只是把后面的数字往前提,但是并不会把要去掉的数字向后挪

eg:1,0,2,0,3

remove(vec.begin(),vec.end(),0)

1,2,3,0,3

后面原来的东西是不变的

解法二虽然写着复杂但时空复杂度与1相似,自带函数比较快

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int n=nums.size();
        // if(n==0) return;
        nums.erase(remove(nums.begin(),nums.end(),0),nums.end());
        int n1=nums.size();
        if(n1!=n)
        {
            vector<int> ad(n-n1,0);
            nums.insert(nums.end(),ad.begin(),ad.end());
        }
        
    }
};

 LC279

四平方数和定理的题,

用原理不具有推广,但是return !!a+!!b是点睛之笔。原本范围很大的int数通过两次取反变成了0/1。使得结果可控

class Solution {
public:
    int numSquares(int n) {
        while (n % 4 == 0) n /= 4;
        if (n % 8 == 7) return 4;
        for (int a = 0; a * a <= n; ++a) {
            int b = sqrt(n - a * a);
            if (a * a + b * b == n) {
                return !!a + !!b;
            }
        }
        return 3;
    }
};

 

但还是可以用DP做

DP有很多种,这个是和上楼梯一样,不断递推的DP,如何递推,发现问题联系是关键,平方项的应用是点睛之笔

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,INT_MAX);
        dp[0]=0;
        //是否带等号很关键,这里初始化了n+1自然可以带
        for(int i=0;i<=n;i++)
        {
            for(int j=1;i+j*j<=n;j++)
            {
                dp[i+j*j]=min(dp[i+j*j],dp[i]+1);
            }
        }
        //vector.back() vector[n]等价,back就是返回最后一个元素
        return dp[n];
    }
};

 LC280

摇摆数组,排列是 小 大 小 大。。。依次这种顺序

#include
#include
#include<string>
#include
using namespace std;
class Solution
{
public:
void wiggleSort(vector<int>& nums)
{
int n=nums.size();
//先排序,再两两交换
sort(nums.begin(),nums.end());
//从二开始,每次加二
for(int i=2;i2) { swap(nums[i],nums[i-1]); } } }; int main() { vector<int> input={1,2,42,4,1,5,4363,4,6,24}; Solution().wiggleSort(input); for(auto i:input) { cout<endl; } return 0; }

方法二:抓住关键问题,若摇摆,奇偶不同情况,与前一个数的大小情况不同,以此为突破口

#include
#include
#include<string>
#include
using namespace std;
class Solution
{
public:
void wiggleSort(vector<int>& nums)
{
//注意判空以及特殊情况
if(nums.size()<=1) return;
for(int i=1;ii)
{
    if(i%2==1&&nums[i]1]||i%2==0&&nums[i]>nums[i-1])
        swap(nums[i],nums[i-1]);
}
}
};
int main()
{
vector<int> input={1,2,42,4,1,5,4363,4,6,24};
Solution().wiggleSort(input);
for(auto i:input)
{
cout<endl;
}
return 0;
}

 PS:默认知识点,map内部自动按照key值排序,本身有序,所以无需额外操作,与之对应unordered_map。这次用一个实际代码写出了整体实验流程。通过实际操作来验证知识点是好的行为希望以后发扬光大

#include
using namespace std;
int main()
{
    vector<int> test={1,43,32,31,43,5,42,4,123};
    map<int,int> test1;
    for(auto i:test)
    {
        test1[i]++;
    }
    for(auto i:test1)
        cout<endl;
    return 0;
}

最后结果就是把vector中的值排好序的,记得在用map输出值时,要标明是first 还是second的否则会无法输出

PS:

1、什么是堆?

堆是一种非线性结构,(本篇随笔主要分析堆的数组实现)可以把堆看作一个数组,也可以被看作一个完全二叉树,通俗来讲堆其实就是利用完全二叉树的结构来维护的一维数组

按照堆的特点可以把堆分为大顶堆小顶堆

大顶堆:每个结点的值都大于等于其左右孩子结点的值

小顶堆:每个结点的值都小于等于其左右孩子结点的值

(堆的这种特性非常的有用,堆常常被当做优先队列使用,因为可以快速的访问到“最重要”的元素)

 默认是大顶堆,小顶堆这样声明

priority_queue, greater> q;

你可能感兴趣的:(0207今天是15的一天冲鸭)