筆試DAY4

雞鴨分類(類雙指針)

題目描述:
農場有n只雞鴨排爲一個隊伍,雞用“C”表示,鴨用“D”表示。當雞鴨挨着時會產生矛盾。需要對所排的隊伍進行調整,使雞鴨各在一邊。每次調整隻能讓相鄰的雞和鴨交換位置,現在需要儘快完成隊伍調整,你需要計算出最少需要調整多少次可以讓上述情況最少。例如:CCDCC->CCCDC->CCCCD這樣就能使之前的兩處雞鴨相鄰變爲一處雞鴨相鄰,需要調整隊形兩次。

輸入描述:
輸入一個長度爲N,且只包含C和D的非空字符串。
輸出描述:
使得最後僅有一對雞鴨相鄰,最少的交換次數。
在這裏插入圖片描述

思路:
交換最後得到的結果只有兩種,雞左鴨右,鴨左雞右
在代碼中可以把‘C’都全移到左邊或者把‘D’全移到左邊,去最小者即可

#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    string s;
    cin >> s;
    int count = 0;
    int sumC = 0;
    int sumD = 0;
    // 把C往左移
    for(int i = 0; i<s.size(); i++)
    {
        if(s[i] == 'C'){   //單引號
            sumC += i-count++;  //********
        }
    }
 
    // 把D往左移
    count = 0;   //重置
    for(int i = 0; i < s.size(); i++)
    {
        if(s[i] == 'D'){
            sumD += i-count++;   //********
        }
    }
    cout << min(sumC, sumD) << endl;
    return 0;
}

其中count計數這是第幾個c/d(從0開始)i-count爲第i個字符需要移動的個數
輸入:cin>>“CCDCC”
C左移:
i=0,s[1]=c,sumc=0+0-0;
i=1,s[1]=c,sumc=0+1-1;
i=2,s[2]=d;
i=3,s[3]=c,sumc=0+3-2;
i=4,s[4]=c,sumc=1+4-3=2;
D左移:
i=0,s[1]=c;
i=1,s[1]=c;
i=2,s[2]=d,sumd=0+2-0=2;
i=3,s[3]=c;
i=4,s[4]=c;
輸出:cout<<2

比特幣最佳買賣時間

題目描述:
給定一個正整數數組,它的第 i 個元素是比特幣第 i 天的價格。
如果你最多隻允許完成一筆交易(即買入和賣出一次),設計一個算法來計算你所能獲取的最大利潤。注意你不能在買入比特幣前賣出。

輸入描述:
正整數數組,爲以空格分隔的n個正整數
輸出描述:
最大利潤
在這裏插入圖片描述
C++中cin的詳細用法
ctrl+z結束

#include<bits/stdc++.h>
using namespace std;
 
int main() {
    int n, mi = INT_MAX, maxProfit = 0;
    while(cin >> n) { //*****
        maxProfit = max(n - mi, maxProfit);
        mi = min(n, mi);
    }
    cout << maxProfit;
    return 0;
}
import java.util.Scanner;
import java.util.ArrayList;
public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        ArrayList<Integer> coin=new ArrayList<>();
        while(in.hasNextInt()){
            coin.add(in.nextInt());
        }
        Integer[] co=new Integer[coin.size()];
        coin.toArray(co);
        int profit=0;
        for(int i=co.length-1;i>=0;i--)
            for(int j=0;j<i;j++){
                profit=Math.max((co[i]-co[j]),profit);
            }
        System.out.println(profit);
    }
}

愛喫喵糧的小貓(貪心)

題目描述:
小招喵喜歡喫喵糧。這裏有 N 堆喵糧,第 i 堆中有 p[i] 粒喵糧。喵主人離開了,將在 H 小時後回來。
小招喵可以決定她喫喵糧的速度 K (單位:粒/小時)。每個小時,她將會選擇一堆喵糧,從中喫掉 K 粒。如果這堆喵糧少於 K 粒,她將喫掉這堆的所有喵糧,然後這一小時內不會再喫更多的喵糧。

小招喵喜歡慢慢喫,但仍然想在喵主人回來前喫掉所有的喵糧。返回她可以在 H 小時內喫掉所有喵糧的最小速度 K(K 爲整數)。

輸入描述:
第一行輸入爲喵糧數組,以空格分隔的N個整數
第二行輸入爲H小時數
輸出描述:
最小速度K
在這裏插入圖片描述

貪心 + 二分查找
理論最小進食速度: 所有喵糧求和 / 給定的小時數
理論最大進食速度:最大堆的喵糧數
在這兩個之間二分查找最小實際可行進食速度即可
注:這是一個lower_bound的二分問題,即求最左邊滿足條件的值 需要相應修改二分查找

#include <bits/stdc++.h>
using namespace std;
 
vector<int> arr;
int H, tmp, sum = 0, res, mmax = 0, mmin; 
 
bool solve(int x, int H) {//x爲速度
    int res = 0;//喫完所有貓糧所需時間
    for(int i = 0; i < arr.size(); i++) {
        res += (arr[i] % x == 0) ? arr[i] / x: arr[i] / x + 1;
    }
    return res <= H;
}
 
int main() {
    string line; getline(cin, line);
    istringstream iss(line);
    while(iss >> tmp) {
        arr.push_back(tmp);
        mmax = max(mmax, tmp);
        sum += tmp;
    }
    scanf("\n%d", &H);
    
    mmin = (sum % H == 0) ? sum / H : sum / H + 1; //理論min
    
    while(mmin < mmax) {  //二分查找終止條件
        res = (mmin + mmax) / 2;
        if(solve(res, H)) mmax = res;//滿足條件時 將右邊屆設爲中間值
        else mmin = res + 1;
        if(solve(mmin, H)) break;//左邊界滿足時 終止
    }
    cout<<mmin<<endl;//結果爲左邊界
}
#include <bits/stdc++.h>
using namespace std;
 
int main(){
    int x,h;
    vector<int> p;
    while(cin>>x)
        p.push_back(x);
    int n = p.size()-1;
    h = p[n];   //****關於輸入的處理
    
    int k = 1, t;
    do{
        t = 0;
        for(int i=0;i<n;i++)
            t += ceil(1.0*p[i]/k);
        k++;
    }while(t>h);
    cout<<k-1<<endl;
    return 0;
}

x遊戲

題目描述:
我們稱一個數 X 爲好數, 如果它的每位數字逐個地被旋轉 180 度後,我們仍可以得到一個有效的,且和 X 不同的數。要求每位數字都要被旋轉。

如果一個數的每位數字被旋轉以後仍然還是一個數字, 則這個數是有效的。0, 1, 和 8 被旋轉後仍然是它們自己;2 和 5 可以互相旋轉成對方;6 和 9 同理,除了這些以外其他的數字旋轉以後都不再是有效的數字。

現在我們有一個正整數 N, 計算從 1 到 N 中有多少個數 X 是好數?

輸入描述:
輸入正整數N
輸出描述:
輸出1到N中好數個數
在這裏插入圖片描述
C++中int與string的相互轉換

#include <bits/stdc++.h>
using namespace std;

bool isGood(int i){
    string s = to_string(i);
    string rotate;/////****
    for(int j=0;j<s.length();j++){
        if(s[j] == '0' || s[j] == '1' || s[j] == '8'){
            rotate[j] = s[j];continue;
        }
        if(s[j] == '2'){
            rotate[j] = '5';continue;
        }
        if(s[j] == '5'){
            rotate[j] = '2';continue;
        }
        if(s[j] == '6'){
            rotate[j] = '9';continue;
        }
        if(s[j] == '9'){
            rotate[j] = '6';continue;
        }
        else{
            return false;
        }
    }
    int after_rotate = atoi(rotate.c_str());
    if(i == after_rotate){
        return false;
    }
    return true;
}
int main(){
    int n,count = 0;
    cin>>n;
    for(int i=1;i<=n;i++){
        if(isGood(i)){
            count++;
        }
    }
    cout<<count<<endl;
    return 0;
}

跳格子游戲

題目描述:
假設你正在玩跳格子(所有格子排成一個縱列)遊戲。需要 跳完n 個格子你才能抵達終點。
每次你可以跳 1 或 2 個格子。你有多少種不同的方法可以到達終點呢?
注意:給定 n 是一個正整數。

輸入描述:格子數n
輸出描述:跳完n個格子到達終點的方法
在這裏插入圖片描述

狀態轉移公式:
當前階梯可以由前一級階梯跳一級到達,也可由前兩級階梯跳兩級到達。

#include <iostream>
using namespace std;

int main(){
    int n;
    cin>>n;
    int dp[n] = {0};
    dp[0] = 1;
    dp[1] = 2;
    for(int i=2;i<n;i++){
        dp[i] = dp[i-1] + dp[i-2];
    }
    cout<<dp[n-1]<<endl; 
    return 0;
}

糖果分配(動態規劃)

題目描述:
假設你是一位很有愛的幼兒園老師,想要給幼兒園的小朋友們一些小糖果。但是,每個孩子最多隻能給一塊糖果。對每個孩子 i ,都有一個胃口值 gi ,這是能讓孩子們滿足胃口的糖果的最小尺寸;並且每塊糖果 j ,都有一個尺寸 sj 。如果 sj >= gi ,我們可以將這個糖果 j 分配給孩子 i ,這個孩子會得到滿足。你的目標是儘可能滿足越多數量的孩子,並輸出這個最大數值。
注意:
你可以假設胃口值爲正。
一個小朋友最多隻能擁有一塊糖果。

輸入描述:
第一行輸入每個孩子的胃口值
第二行輸入每個糖果的尺寸
孩子數和糖果數不超過1000
輸出描述:
能滿足孩子數量的最大值
在這裏插入圖片描述
sort函數對vector容器進行排序

#include <bits/stdc++.h>
using namespace std;
 
int main(){
    string S;
    vector<int> g,s;
    getline(cin, S);
    stringstream ss1(S);
    int x, cnt=0;
    while(ss1>>x)
        g.push_back(x);
    getline(cin, S);
    stringstream ss2(S);
    while(ss2>>x)
        s.push_back(x);
        
    sort(g.begin(), g.end());
    sort(s.begin(), s.end());
    for(int i=0,j=0;i<g.size() && j<s.size();){ 
        if(g[i]<=s[j]){
            cnt++;
            i++;
            j++;
        }else
            j++;
    }
    cout<<cnt<<endl;
    return 0;
}
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
    int num;
    vector<int> g;
    vector<int> s;
    while(cin>>num)
    {
        g.push_back(num);
        if(getchar()=='\n')  //*****
            break;
    }
    while(cin>>num)
    {
        s.push_back(num);
        if(getchar()=='\n')
            break;
    }
    sort(g.begin(),g.end());//****
    sort(s.begin(),s.end());
    int sum=0;
    for(int i=0,j=0;j<s.size();j++)
    {
        if(i>=g.size())
            break;
        if(s[j]>=g[i])
        {
            sum++;
            i++;
        }
    }
    cout<<sum;
}

員工考勤記錄(斐波那契)

題目描述:
給定一個字符串來代表一個員工的考勤紀錄,這個紀錄僅包含以下兩個字符:
‘A’ : Absent,缺勤
‘P’ : Present,到場
如果一個員工的考勤紀錄中不超過兩個’A’(缺勤),那麼這個員工會被獎賞。
如果你作爲一個員工,想在連續N天的考勤週期中獲得獎賞,請問有多少種考勤的組合能夠滿足要求

輸入描述:
考勤週期的天數N(正整數)
輸出描述:
這N天裏能獲得獎賞的考勤組合數
在這裏插入圖片描述

#include <bits/stdc++.h>
using namespace std;
 
int cal(int n){
    if(n==2){
        return 1;
    }
    else{
        return (cal(n-1)+n-1);
    }
}
int main(){
    int n,count;
    cin>>n;
    count = n + 1 + cal(n);
    cout<<count<<endl;
    return 0;
}

總結目前牛客問題 :
第一,沒有循環輸入問題,
第二 有循環輸入問題,
第三 輸入有多餘空格問題 ,
第四 中間插入多餘空行問題 …

解碼方法(**動態規劃)

題目描述:
一條包含字母 A-Z 的消息通過以下方式進行了編碼:
‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26
給定一個只包含數字的非空字符串,請計算解碼方法的總數。

輸入描述:
12可以解碼成“AB”,“L”這兩種
輸出描述:
解碼方法的總數
在這裏插入圖片描述

#include <iostream>
using namespace std;
int main(void){
    string s;
    int len;
    cin>>s;
    len = s.length();
    int *dp = new int[len+1]{};
    dp[0] = 1;
    for(int i = 1; i <= len; ++i){
        if(s[i-1] != '0')
            dp[i] += dp[i-1];
        if(i >= 2 && s[i-2] == '1' || s[i-2] == '2' && s[i-1] < '7')
            dp[i] += dp[i-2];
    }
    cout<<dp[len]<<endl;
    delete dp;
    return 0;
}
s = input()
n = len(s)
x_1 = 1
for i in range(n):
  if i == 0:
    x_2 = 1
  else:
    if int(s[i - 1: i + 1]) <= 26:
      x_1, x_2 = x_2, x_1 + x_2
    else:
      x_1 = x_2
print(x_2)

漂流船問題(雙指針)

題目描述:
公司組織團建活動,到某漂流聖地漂流,現有如下情況:
員工各自體重不一,第 i 個人的體重爲 people[i],每艘漂流船可以承載的最大重量爲 limit。
每艘船最多可同時載兩人,但條件是這些人的重量之和最多爲 limit。
爲節省開支,麻煩幫忙計算出載到每一個人所需的最小船隻數(保證每個人都能被船載)。

輸入描述:
第一行輸入參與漂流的人員對應的體重數組,
第二行輸入漂流船承載的最大重量
輸出描述:
所需最小船隻數
在這裏插入圖片描述

#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main(){
    int num,limit;
    vector<int> people;
    while(cin>>num){
        people.push_back(num);
        if(getchar() == '\n'){
            break;
        }
    }
    cin>>limit;
    sort(people.begin(),people.end());
    
    int boat = 0;
    int i = 0;
    int j = people.size()-1;
    while(i<j){
        if(people[i] + people[j] <= limit){
            i++;
            j--;
        }
        else{
            j--;
        }
        boat++;
    } 
    if(i == j){
        boat++;
    }
    
    cout<<boat<<endl;
    return 0;
}

**推倒吧骨牌

題目描述:
在這裏插入圖片描述
輸入描述:
輸入爲一個長度不超過1000的,僅包含‘L’,‘R’,‘.’的字符串
輸出描述:
根據輸入,輸出一個僅由‘L’,‘R’,‘.’組成的結果字符串
在這裏插入圖片描述

思路:
從這往右遍歷,用flag記錄之前是否有右傾;用pos記錄上次右傾位置;
遍歷無非兩種情況:
當前是左傾:1.在最左側,直接往左邊倒完。2.前面存在右傾:相擁而倒;
當前是右傾:1.前面有右傾:處理前面的右傾,更新pos;2:前面無右傾,設置flag和pos;
遍歷結束後再處理是否有最後殘留的那個flag;

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string data;
    while(cin>>data)
    {
        int rflag=0;
        int pos;
        int len=data.size();
        for(int i=0;i<len;i++)
        {
            if(data[i]=='L')
            {
                int cur=i-1;
                if(rflag==0)
                {
                    while(cur>=0&&data[cur]=='.')
                    {
                        data[cur]='L';cur--;
                    }
                }
                else
                {
                    int l=pos+1;
                    while(cur>l)
                    {
                        data[cur]='L';
                        data[l]='R';
                        l++;cur--;
                    }
                    rflag=0;
                }
            }
            if(data[i]=='R')
            {
                if(rflag==0)
                {
                    rflag=1;
                    pos=i;
                }
                else{
                    pos=i;
                    int cur=i-1;
                    while(cur>=0&&data[cur]=='.')
                    {
                        data[cur]='R';cur--;
                    }
                }
            }
        }
        if(rflag)
        {
            int cur=pos+1;
            while(cur<len)
            {
                data[cur]='R';
                cur++;
            }
        }
        cout<<data<<endl;
    }
    return 0;
}

leetcode:推多米諾骨牌
在這裏插入圖片描述

import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        char[] chs = scanner.next().toCharArray();
        int len = chs.length;
        int[] values = new int[len];
 
        // 第一遍從左往右遍歷,遇到R就賦值length,接下來如果是.則遞減,直到遇到L清零
        int value = 0;
        for (int i = 0; i < len; i++) {
            if (chs[i] == 'R') {
                value = len;
            } else if (chs[i] == 'L') {
                value = 0;
            } else {
                // 保證L之後遇到.仍舊賦值0而不是負數
                value = Math.max(value - 1, 0);
            }
            // values數組加上value值
            values[i] += value;
        }
 
        // 第二遍從右往左遍歷,遇到L就賦值length,接下來如果是.則遞減,直到遇到R清零
        value = 0;
        for (int i = len - 1; i >= 0; --i) {
            if (chs[i] == 'L') {
                value = len;
            } else if (chs[i] == 'R') {
                value = 0;
            } else {
                // 保證R之後遇到.仍舊賦值0而不是負數
                value = Math.max(value - 1, 0);
            }
            // values數組減去value值
            values[i] -= value;
        }
 
        StringBuilder result = new StringBuilder();
        // values值大於0則爲R,小於0則爲L,等於0則爲.
        for (int i : values) {
            result.append(i > 0 ? 'R' : i < 0 ? 'L' : '.');
        }
        System.out.println(result);
    }
}
"""
LR匹配問題,記錄之前方向,分4類討論LL/RL/RR/LR
"""
import math
 
if __name__ == "__main__":
    s = list(input().strip())
    ans = s[:]
    t = pl = pr = 0
    flag = '0'
    while t < len(s):
        while t < len(s) and s[t] == '.': t += 1
        if t >= len(s): break
        if s[t] == 'L':
            if flag == '0' or flag == 'L':
                for i in range(pl, t):
                    ans[i] = 'L'
            else:
                pl = t
                for i in range(pr, math.ceil((pr + pl) / 2)):
                    ans[i] = 'R'
                for i in range(math.floor((pr + pl) / 2) + 1, pl):
                    ans[i] = 'L'
            flag = 'L'
        elif s[t] == 'R':
            if flag == 'R':
                for i in range(pr + 1, t):
                    ans[i] = 'R'
            pr = t
            flag = 'R'
        t += 1
    if pr > pl:
        for i in range(pr, len(s)):
            ans[i] = 'R'
    print(''.join(ans))
 

帶點多米諾骨牌旋轉
等價多米諾骨牌的數量
多米諾骨牌效應

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章