day010.补录--栈与队列+好未来客户端开发一面总结

20.有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

1.思路:栈经典的题目,定义一个栈,遍历字符串,根据匹配到的符号,将对称的符号加入到栈中,如果均不是,则返回FALSE,若栈不为空,则判断当前字符与栈顶是否相同(因为如果二者相邻,则一定是对称的,否则就不是有效括号),若相同,将此元素弹出栈,继续遍历。

class Solution {
public:
    bool isValid(string s) {
       stack<char> st;
       for(char c:s){
         if(c=='{'){
            st.push('}');
         }else if(c=='('){
            st.push(')');
         }else if(c=='['){
            st.push(']');
         }else if(st.empty()){
            return false;
        }
        else{
              if(st.top()==c){
                st.pop();
              }else{
                return false;
              }
            }
         }
       return st.empty();
    }
};

1047.删除字符串中的相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

 思路:首先,遍历字符串,如果当前栈不为空并且栈顶元素等于当前字符,则将栈顶元素移除,否则将该字符压入栈中,这样就可以实现相邻字符删除的操作,在下面,将栈中元素转移到字符串上,这时要注意,栈是先进后出的规则,所以要将字符串在翻转过来,此时就是我们要求得的字符串。

class Solution {
public:
    string removeDuplicates(string s) {
        stack<char> st;
        for(char c:s){
           if(!st.empty()&&st.top()==c){
             st.pop();
           }else{
            st.push(c);
           }
        }
        string str;
      while(!st.empty()){
        str+=st.top();
        st.pop();
      }
      reverse(str.begin(),str.end());
        return str;
    }
};

150.逆波兰表达式求值

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

思路:怎么说呢,这道题不难,思路也很清晰,只要你了解后缀表达式,就可以写明白,也是一道可以用栈来解决的题目。首先定义一个栈,用来存储值,遍历字符串数组,如果是四个运算符号的话就将栈弹出并计算,如果不是运算符,就将它压入栈中(注意,由于是字符串数组,所以压入栈之前要将其中的字符串转成整数才能使用)。

class Solution {
public:
    int evalRPN(vector<string>& nums) {
        stack<int> st;
        for(int i=0;i<nums.size();i++){
            if(nums[i]=="+"||nums[i]=="-"||nums[i]=="*"||nums[i]=="/"){
                int a=st.top();
                st.pop();
                int b=st.top();
                st.pop();
                if(nums[i]=="+"){
                    st.push(a+b);
                }else if(nums[i]=="-"){
                    st.push(b-a);
                }else if(nums[i]=="*"){
                    st.push(a*b);
                }else if(nums[i]=="/"){
                    st.push(b/a);
                }
            }else{
                    st.push(stoi(nums[i]));
                }
        }
        return st.top();
    }
};

239.滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

 1.错误思路:最开始我想用一种比较简单的方式解决这个问题,就是定义一个函数,每次滑动窗口都需要计算一下当前窗口下的最大值,这样会导致时间复杂度很高,我在LeetCode运行之后,发现超时了。。。

class Solution {
public:
    int getMax(vector<int>& nums,int slow,int fast){//
    int maxValue=-INT_MAX;
        for(int i=slow;i<=fast;i++){
            if(nums[i]>maxValue){
                maxValue=nums[i];
            }
        }
        return maxValue;
    }
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int slow=0;
        int fast=k-1;
        vector<int> result;
        for(int i=0;i<nums.size()-k+1;i++){
            int maxValue=getMax(nums,slow++,fast++);
            result.push_back(maxValue);
        }
        return result;
    }
};

2.单调队列:维护一个单调队列,要保证单调队列中的队头是最大元素,因此在push函数中,我判断如果它要加入的值比当前队列的尾部元素要大,则将尾部元素弹出,直到双端队列为空或者遇到比它要大的值(此时队列内为单调递减)。在pop函数,我判断如果要移除的元素等于队列头部元素,则弹出,否则不做任何操作(因为此时队列在push的时候就已经将它移除了)。上述就是核心思想,在主函数中,只需要现将前k个元素加进去,然后判断push和pop进行操作即可。

class Solution {
public:
    class myQueue{//维护一个递减的单调队列 对头为最大值
        public:
        deque<int> que;
        //如果窗口移除的元素value等于单调队列的出口元素
        //那么队列弹出元素,否则不用任何操作
        void pop(int val){
            if(!que.empty()&&val==que.front()){
                que.pop_front();
            }
        }
        //如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,
        //直到push元素的数值小于等于队列入口元素的数值为止
        void push(int val){
            while(!que.empty()&&que.back()<val){
                que.pop_back();
            }
            que.push_back(val);
        }
        int front(){
            return que.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        myQueue que;
        vector<int> result;
        for(int i=0;i<k;i++){
            que.push(nums[i]);
        }
     result.push_back(que.front());
        for(int i=k;i<nums.size();i++){
            que.pop(nums[i-k]);
            que.push(nums[i]);
            result.push_back(que.front());
        }
        return result;
    }
};

 347.前K个高频元素

思路:用哈希表将向量数组中的数字和出现频率统计一下pair{元素出现的频率,元素的值},然后,根据大顶堆将哈希表中的数字加入到大顶堆中,大顶堆会按照从大到小的顺序排好,只需要遍历前K个元素就可以了。

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> mp;//对应的值 出现次数
        for(auto& i:nums){
            mp[i]++;
        }
        priority_queue<pair<int,int>> pq; //优先队列
        for(auto& i:mp){
            pq.push({i.second,i.first});//元素出现的频率,元素值
        }
        vector<int> res;
        while(k--){
            res.push_back(pq.top().second);
            pq.pop();
        }
        return res;
    }
};

总结一下昨天的好未来客户端实习一面:

1.可能是因为客户端的原因,他开头就问了我很多关于线程池的问题,我对此没多少准备,只能凭借日常积累回答。。。

2.之后就开始问了一些Linux系统的基础问题,线程和进程的区别,子进程和父进程地址空间是共享的吗?不是共享的,他们又自己独立的地址空间,在fork创建子进程之后,父进程和子进程共享相同的物理页面,只有当其中的一个进程尝试修改共享页面时,操作系统才会复制该页,使得修改只影响修改发生的那个进程

3.TCP四次挥手流程 
4.TIME_WAIT作用
5.C++运行前的步骤 --预处理,编译,汇编,链接
6.内存分配
7.const用法
8.互斥锁和自旋锁:当时这道题说错了,互斥锁是阻塞锁,互斥锁保证在任意时刻,只有一个进程能够进入临界区,当一个线程获取到互斥锁之后,其他线程就会处于阻塞的状态,直到该线程释放锁。而自旋锁是一种忙等待锁,当一个线程发现自旋锁被其他线程占用时,它会一直占用CPU资源进行循环等待,而不进入阻塞状态,直到该自旋锁可用。

读写锁:读写锁允许多个线程同时对共享数据进行读操作,但只允许单个线程进行写操作,当有线程写入时(拥有写锁时),其他线程无法同时进行读操作,(读写互斥)防止数据的不一致性。

适用场景:互斥锁:适用于临界区资源访问时间较长或存在阻塞等情况。

自旋锁:适用于临界区资源访问时间较短且线程竞争不激烈的情况。

读写锁适用于读操作远远多于写操作的场景可以提高并发读的性能。
9.进程间通信几种方式 挑一个说说具体用法(Linux和window的区别)
10.项目如何实现断点续传
11.进程和线程的区别
12.子进程和父进程是共享同一块内存的吗
13.堆和栈的区别
14.线程栈的大小 windows 1mb  Linux 默认8mb
15.算法题 数组中最长的子序列,要求空间复杂度O(n)时间复杂度O(nlogn)

 还落下一道题,翻转字符串,明天补上,再加上面试算法题,面试官对我编写的时间复杂度不满意。

  • 21
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据星历计算卫星位置的方法是比较复杂的,需要用到天文学中的一些计算方法和公式,因此需要一些较为复杂的计算。以下是一个大致的计算流程: 1. 将给定的日期时间转换为儒略日(Julian day)。 2. 根据儒略日计算相应的世纪数。 3. 计算卫星的平近点角(Mean Anomaly)和升交点赤经(Right Ascension of Ascending Node)。 4. 计算卫星的轨道倾角(Inclination)、近地点角距(Argument of Perigee)、半长轴(Semi-Major Axis)等轨道参数。 5. 计算卫星的真近点角(True Anomaly)。 6. 根据卫星的真近点角、轨道参数和世纪数等信息,计算卫星的位置。 下面是一个简单的 C++ 代码示例,可以用来计算给定日期时间的 C01 卫星位置: ```c++ #include <iostream> #include <cmath> using namespace std; const double PI = 3.14159265358979323846; const double GM = 3.986005e14; const double OMEGA_E = 7.2921151467e-5; const double MU_GPS = 3.986005e14; const double C_GPS = 299792458.0; // 计算儒略日 double julian_day(int year, int month, int day, int hour, int minute, int second) { int a = (14 - month) / 12; int y = year + 4800 - a; int m = month + 12 * a - 3; int jdn = day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045; double jd = jdn + ((double)hour - 12) / 24 + (double)minute / 1440 + (double)second / 86400; return jd; } // 计算卫星位置 void satellite_position(double t, double *pos) { // 从星历中读取轨道参数等信息 double a = 26559700.0; double e = 0.008777161321; double i = 0.9757632172; double O = 0.5405171530; double w = 3.510029399; double M = 0.0; double n = sqrt(MU_GPS / pow(a, 3)); double t0 = 0.0; // 计算平近点角 double E = M + e * sin(M); double E0 = E; while (abs(E - E0) > 1e-12) { E0 = E; E = M + e * sin(E); } double v = 2 * atan(sqrt((1 + e) / (1 - e)) * tan(E / 2)); double r = a * (1 - e * cos(E)); // 计算卫星位置 double x = r * (cos(O) * cos(w + v) - sin(O) * sin(w + v) * cos(i)); double y = r * (sin(O) * cos(w + v) + cos(O) * sin(w + v) * cos(i)); double z = r * sin(w + v) * sin(i); double dt = t - t0; pos[0] = x * cos(OMEGA_E * dt) + y * sin(OMEGA_E * dt); pos[1] = -x * sin(OMEGA_E * dt) + y * cos(OMEGA_E * dt); pos[2] = z; } int main() { int year = 2020; int month = 12; int day = 23; int hour = 23; int minute = 0; int second = 0; double jd = julian_day(year, month, day, hour, minute, second); double t = (jd - 2451545.0) / 36525.0; double pos[3]; satellite_position(t, pos); cout << "C01卫星位置:" << endl; cout << "X = " << pos[0] << " m" << endl; cout << "Y = " << pos[1] << " m" << endl; cout << "Z = " << pos[2] << " m" << endl; return 0; } ``` 注意:由于卫星位置的计算涉及很多天文学中的参数和公式,因此以上代码仅供参考,具体实现需要根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值