编程之旅-Day44

目录

Day44-学习内容:

1.剑指Offer

面试题59:滑动窗口最大值(牛客网无)

面试题30:包含min函数的栈

 2.华为机试题

例1:汽水瓶

例2:删除字符串中出现次数最少的字符

例3.合唱队


1.剑指Offer

面试题59:滑动窗口最大值(牛客网无)

题目描述:

思路:

最大子序和思想基本是一样的

用一个队列存放数组下标,设两个指针lr,其中l指向当前队列中数最大的数组下标,r指向最后一个进队列的元素,如果新进元素比队尾大,那么就弹出队尾元素,因为队尾元素的生存能力已经不如新进的元素强,没有存在意义

代码:

剑指offer解法,超出时间限制不能通过leetcode

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> maxSlidingWindow;
        while(nums.size()>=k&&k>=1){
            deque<int> q;
            
            for(int i=0;i<nums.size();i++){
                while(!q.empty()&&nums[i]>=nums[q.back()]){
                    q.pop_back();
                }
                q.push_back(i);
            }
            
            for(int i=k;i<nums.size();i++){
                maxSlidingWindow.push_back(nums[q.front()]);
                while(!q.empty()&&nums[i]>=nums[q.back()]){
                    q.pop_back();
                }
                if(!q.empty()&&q.front()<=int(i-k)){
                    q.pop_front();    
                }
                q.push_back(i);
            }
            maxSlidingWindow.push_back(nums[q.front()]);
        }
        return maxSlidingWindow;
    }
};
leetcode通过解法

class Solution
{
public:
    vector<int> maxSlidingWindow(vector<int> &nums, int k)
    {
        vector<int> ans;
        if (nums.empty())
            return ans;

        int q[nums.size() + 5];
        memset(q, 0, sizeof(q));
        int l = 0, r = 0;
        for (int i = 0; i < nums.size(); ++i)
        {
            while (l <= r && q[l] <= i - k)//超出窗口,弹出元素
                ++l;
            while (l <= r && nums[q[r]] < nums[i])//队尾元素生存能力差,弹出
                --r;
            q[++r] = i;//进队
            if (i + 1 >= k)//窗口达到k,放入答案中
                ans.push_back(nums[q[l]]);
        }
        return ans;
    }
};

 

面试题30:包含min函数的栈

题目描述:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

思路:使用辅助栈

代码:

class Solution {
public:
    stack<int> stack1,stack2;
    void push(int value) {
        stack1.push(value);
        if(stack2.empty()||value<stack2.top()){
            stack2.push(value);
        }
    }
    void pop() {
        if(stack1.top()==stack2.top()){
            stack2.pop();
        }
        stack1.pop();
    }
    int top() {
        return stack1.top();
    }
    int min() {
        return stack2.top();
    }
};

 2.华为机试题

例1:汽水瓶

题目描述:

有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝? 

输入描述:

输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=100),表示小张手上的空汽水瓶数。n=0表示输入结束,你的程序不应当处理这一行。

输出描述:

对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。

示例1

输入

3
10
81
0

输出

1
5
40

代码:

方法1:通过数学分析,最后获得的饮料数是总空瓶数整除2 。

#include <iostream>

using namespace std;

int main(){
    int n;
    while(cin>>n){
        cout << n/2 << endl;
    }
    return 0;
}

方法2:递归问题

3个瓶子换1瓶水+1个空瓶子,两个瓶子换1瓶水+0个空瓶子,1个瓶子换0瓶水。

f(1) = 0

f(2) = 1

f(3) = 1

f(4) = f(2)+1    //4个瓶子,其中3个可以换1瓶水+1个空瓶,所以是f(2)+1

f(5) = f(3)+1    //3个瓶子换1瓶水+1个空瓶,所以是f(3)+1

...

f(n) = f(n-2)+1 

#include <iostream>

using namespace std;

int f(int n){
    if(n<=1) return 0;
    if(n==2) return 1;
    return f(n-2)+1; 
}

int main(){
    int n;
    while(cin>>n){
        cout << f(n) << endl;
    }
    return 0;
}

例2:删除字符串中出现次数最少的字符

题目描述:

实现删除字符串中出现次数最少的字符,若多个字符出现次数一样,则都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。 

输入描述:

字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。

输出描述:

删除字符串中出现次数最少的字符后的字符串。

示例1

输入

abcdd

输出

dd

代码:

#include <iostream>

using namespace std;

int main(){
    string str;
    while(cin>>str){
        int a[26]={0};
        int len=str.length();
        
        for(int i=0;i<len;i++){   //统计字符个数
            a[str[i]-'a']++;
        } 
        
        int min=a[str[0]-'a'];    //找到最小个数
        for(int i=0;i<len;i++){
            if(a[str[i]-'a']<min){
                min=a[str[i]-'a'];
            }
        }
        
        for(int i=0;i<len;i++){   //删除最小字符
            if(a[str[i]-'a']>min){
                cout<<str[i];
            }
        }
        cout<<endl;   
    }
    return 0;
}
#include <iostream>
#include <map>

 using namespace std;

int main(){
    string str;
    while(cin>>str){
        map<char,int> m;
        for(char i='a';i<='z';i++){   //map置空
            m[i]=0;
        }
        int min=999;
        for(int i=0;i<str.length();i++){  //统计个数并找到最小的个数
            m[str[i]]++;
            if(m[str[i]]<min){
                min=m[str[i]];
            }
        }
        for(int i=0;i<str.length();i++){
            if(m[str[i]]>min){
                cout<<str[i];
            }
        }
        cout<<endl;   
    }
    return 0;
}

 

例3.合唱队

例1:首先计算每个数在最大递增子串中的位置 

186  186  150  200  160  130  197  200   quene

1      1      1      2       2      1      3     4       递增计数 

然后计算每个数在反向最大递减子串中的位置--->计算反向后每个数在最大递增子串中的位置

200  197  130  160  200  150  186  186   反向quene

1      1      1       2     3      2      3       3      递减计数 

然后将每个数的递增计数和递减计数相加 

186  186  150  200  160  130  197  200   quene

1      1      1      2       2     1      3      4       递增计数 

3      3      2      3       2     1      1      1       递减计数 

4      4      3      5       4     2      4      5       每个数在所在队列的人数+1(自己在递增和递减中被重复计算) 

如160这个数 

在递增队列中有2个人数 

150  160

在递减队列中有2个人数 

160  130

那么160所在队列中就有3个人 

150  160  130

每个数的所在队列人数表达就是这个意思 

总人数 - 该数所在队列人数 = 需要出队的人数 

解析:动态规划,最大递增子序列

代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void callIncSub(vector<int> queue,vector<int> &incNum){
    for(int i=1;i<queue.size();i++){
        for(int j=i-1;j>=0;j--){
            if(queue[i]>queue[j]&&incNum[i]<incNum[j]+1){
                incNum[i]=incNum[j]+1;
            }
        }
    } 
}

int main(){
    int n;
    int h;
    while(cin>>n){
        vector<int> queue;
        vector<int> incNum(n,1);
        vector<int> decNum(n,1);
        vector<int> totalNum;
        
        for(int i=0;i<n;i++){
            cin>>h;
            queue.push_back(h);
        }
        
        callIncSub(queue,incNum);
        reverse(queue.begin(),queue.end());
        callIncSub(queue,decNum);
        reverse(decNum.begin(),decNum.end());
        int max=0;
        for(int i=0;i<n;i++){
            totalNum.push_back(incNum[i]+decNum[i]);
            if(totalNum[i]>max){
                max=totalNum[i];
            }
        }
        cout<<n-max+1<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/linyuhan3232/article/details/89735502