演算法課第6周第1題——402. Remove K Digits
題目描述:
Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.
Note:
- The length of num is less than 10002 and will be ≥ k.
- The given num does not contain any leading zero.
Example 1:
Input: num = "1432219", k = 3 Output: "1219" Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
Example 2:
Input: num = "10200", k = 1 Output: "200" Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
Example 3:
Input: num = "10", k = 2 Output: "0" Explanation: Remove all the digits from the number and it is left with nothing which is 0.
程式程式碼:
簡要題解:class Solution { public: string removeKdigits(string num, int k) { int len = num.size(); // 用一個雙向佇列幫助完成演算法 deque<int> q; // total為去掉k個字元後剩餘的字元總數(k表示需要去掉的字元數) int total = len - k; // 若串長度<=k, 直接輸出0 if (len <= k) { string res = "0"; return res; } // 遍歷 for (int i = 0; i < len; i++) { // 若雙向佇列隊尾的元素比當前訪問的字元更大,則將其去掉,並將需要去掉的字元數量-1(即k-1) // 迴圈,直到佇列為空,或隊尾元素不會比當前訪問元素更大,或是k == 0(即不需要再去掉字元了) while (k != 0 && !q.empty() && q.back() > num[i]) { q.pop_back(); k--; } // 將當前訪問元素放入隊尾(有可能會多出來,之後再處理) q.push_back(num[i]); } // 將佇列中元素放入一個字串 // 此外,只需要放入佇列中前total個元素即可,多餘的後面部分捨棄掉即可 string res = ""; for (int i = 0; i < total; i++) { res += q.front(); q.pop_front(); } // 去除結果開頭的0 int j = 0; while (res[j] == '0') { j++; } res = res.substr(j); // 至少要輸出一個“0”而不是空串 if (res == "") { res = "0"; } return res; } };
本題依舊用到了這兩週所學的貪心演算法。
先理解題意。根據題目描述及所給例子可以看出,本題是要我們去掉一個字串中的k個字元,使剩下的字元為可能的最小值。需要注意兩點,一是最後結果前的0不需要輸出,二是如果k與字串總長度相等,則要輸出0.
考慮如何解這個題目。按常規的方法來想,可以通過遍歷整個陣列,每次如果發現某個字元比它的前一個字元更大,則將這個字元刪去,然後重頭開始迴圈;若沒有符合條件的字元,則在遍歷到最後時將末尾字元刪去,並重頭開始迴圈。這整個操作重複k次。這樣就可以得到題目要求的答案。不過這種演算法每刪除一個字元就要再重頭遍歷一次,顯然時間複雜度會比較大。
考慮進一步優化貪心演算法。可以使用一個雙向佇列來輔助完成。遍歷整個字串,將每個字元都放入雙向佇列尾部,不過在放入之前,先要判斷(若雙向佇列不為空的話)雙向佇列尾部的字元是否比遍歷訪問到的這個字元大,若是,則說明佇列尾部這個字元刪去的話會讓結果變小,故將其刪去,並將k-1(表示需要刪除的字元數量少了一個)重複這個操作直到佇列為空、或是隊尾字元不再比訪問到的字元更大、或是k次刪除次數全部用完(k==0)。當全部的字元都放入雙向佇列後遍歷結束。此時佇列中的元素數量有可能比題目要求的結果更多,接著只要將這個雙向佇列的前len
- k 個元素放入一個空字串即可(len為原字串長度,len - k 表示刪去k個字元後剩餘的長度),佇列中後面部分的元素捨棄即可(相當於上面常規解法中的遍歷時刪除末尾字元)。最後,為了滿足輸出要求,需要將字串前面的0字首去掉,並輸出最終結果。
本題是一道結合了字串的貪心演算法問題,演算法中每次只考慮區域性的一個字元與前面字元的關係,但可以最終得出正確的結果。貪心演算法確實非常有用,不過有時也不容易想到如何使用,需要多加鞏固。
相關推薦
演算法課第6周第1題——402. Remove K Digits
題目描述: Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest
MOOC北京理工《C語言程式設計(上)》第6周第3題:郵票組合
題目內容: 我們寄信都要貼郵票,在郵局有一些小面值的郵票,通過這些小面值郵票中的一張或幾張的組合,可以滿足不同郵件的不同的郵資。 現在,郵局有4種不同面值的郵票。在每個信封上最多能貼5張郵票,面值可相同,可不同。 輸入格式: 四種郵票的面值。 輸出格式: 用這四
第6周作業1-閏年之迴圈判斷
參照了一下網上的;第八,第十三和十四橫所代表的意思 public class LeapYearFor { /** * @param args */ public static void main(String[] args) { // TODO Auto-
C++第6周專案1
【題目】下面的程式存在編譯錯誤。有兩種方法可以修改,請給出這兩種修改方案,在報告中說明你傾向於用哪一種?為什麼?處理此類問題的原則是什麼?class C {private: int x; public: C(int x){this->x= x;}
演算法課第11周第1題——120. Triangle
題目描述: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. For
第16周專案1 驗證演算法(6)堆排序
問題: /* * Copyright (c)2015,煙臺大學計算機與控制工程學院 * All rights reserved. * 檔名稱:專案1-6.cbp * 作 者:張芸嘉 *
2018-2019-1 20165332 《資訊安全系統設計基礎》第6周學習總結
2018-2019-1 20165332 《資訊安全系統設計基礎》第6周學習總結 教材內容總結 一.儲存技術 1,RAM分為靜態RAM和動態RAM 2.DRAM把超單元的內容發回控制器作為響應,行地址i稱為RAS請求,列地址j稱為CAS請求 3.增強的DRAM 快頁模式DRAM 擴充套件
2018-2019-1 20165201 《資訊安全系統設計基礎》第6周學習總結
2018-2019-1 20165201 《資訊安全系統設計基礎》第6周學習總結 內容待完善~~~ 教材學習內容總結 儘量簡單的總結一下本週學習內容 儘量不要抄書,浪費時間 看懂就過,看不懂,學習有心得的記一下 教材學習中的問題和解決過程 (一個模板:我看了這一段文字 (引用文字),有這個問題 (提
中國大學MOOC—基礎學Java語言----第6周程式設計題——單詞長度(5分)
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String
MOOC北京理工《C語言程式設計(上)》第5周第1題:鍛鍊身體吧
題目內容: 沫沫,灰灰和渣渣去鍛鍊身體,如果對他們跑步的距離分別只計整數 a、 b、 c,由於他們身高的差距,造成了 a<=b<=c,並且渣渣跑了N米之後就再也跑不動了。但是,按照他們事先的約定: 只有當 c*c==a*a+b*b 時,他們的鍛鍊才有效果。
MOOC清華《程式設計基礎》第6章第1題:n級臺階問題(遞推法)
題目描述 下n級臺階,每步可下1級或2級臺階。那麼從n級臺階下到地面,共有多少種不同的下臺階方案? 輸入:n 輸出:方案數 輸入格式 多行輸入,每一行輸入一個正整數n,表示n級臺階 輸出格式 每一行輸出n級臺階的方案數 樣例輸入 1 2 樣例輸出 1 2 D
第16周專案1 驗證演算法(7)歸併排序
問題: /* * Copyright (c)2015,煙臺大學計算機與控制工程學院 * All rights reserved. * 檔名稱:專案1-7.cbp * 作 者:張芸嘉 * 完成日期:2015年12月18日 * 版 本 號
多型與虛擬函式-程式設計題#2(C++程式設計第6周)
程式設計題#2 來源: POJ (Coursera宣告:在POJ上完成的習題將不會計入Coursera的最後成績。) 注意: 總時間限制: 1000ms 記憶體限制: 65536kB 描述 下面
第11周專案1——二叉樹演算法驗證
問題及程式碼:/* *Copyright(c++)2015,煙臺大學計算機與控制工程學院 *All rights reserved. *檔名稱:CPP1.cpp *作者:宋 晨 *完成
第12周專案1 圖基本演算法庫
問題: /* * Copyright (c)2015,煙臺大學計算機與控制工程學院 * All rights reserved. * 檔名稱:專案1.cpp * 作 者:張芸嘉 * 完成日期:2015年11月23日 * 版 本 號:v1.0 * 問題
第6章第1講簡單的循環結構
3-9 log 結構 -1 mar src () col pan main() { int sum,i; sum=0; i=1; while(i<=100) { sum=sum+i;
第6周作業
浮點型 color 強制 pri class 解決方法 -s span family 學習內容總結 題目7-1 高速公路超速處罰 1 #include<stdio.h> 2 int main() 3 { 4 int a,b; 5 fl
Linux學習筆記第三周第三次課(2月7日)
配置 學習筆記 使用 con log 搜索 su命令 去掉 start 3.7 su命令root用戶切換到普通用戶命令,su;完全徹底切換 - ,連環境變量,家目錄也切換,命令為#su - aming;查看當前登陸用戶,命令為#whoami;查看當前目錄,命令為#pwd;查
Linux學習筆記第三周第四次課(2月8日)
虛擬機 添加磁盤 acer cto process ued fault print rep 4.1 df命令df,report file system disk space usage匯報文件系統磁盤空間使用情況;df命令格式:df [選項]df -a:all 顯示所有文件
Linux學習筆記第五周第三次課(3月7日)
yum list | grep zsh history tab鍵 alias wc -l 8.1 shell介紹每個用戶都有自己的shell;Bourne人名,為了紀念他;搜索zsh命令,#yum list | grep zsh搜索ksh命令,#yum list | grep ksh邏輯判