2022.01.25刷題
阿新 • • 發佈:2022-01-26
121. 買賣股票的最佳時機 todo
415. 字串相加
感覺邏輯很不清晰...
//我的 string addStrings(string num1, string num2) { reverse(num1.begin(), num1.end()); reverse(num2.begin(), num2.end()); if(num1.size()<num2.size())swap(num1,num2); int tmp = 0; int n = num1.size(), m = num2.size(); for(int i = 0; i< m || tmp;i++){ //這直接是字串模式的大數加法是吧.. 普通的好像挺簡單的. if(i==n) num1+='0'; //不夠了補0 num1[i] += tmp; // if(i<m) num1[i] += num2[i] -'0'; tmp = 0; if(num1[i]>'9'){ num1[i]-=10; tmp = 1; } } reverse(num1.begin(), num1.end()); return num1; }
169. 多數元素
簡單題 可是題解有好多, 我只用了um做.
350. 兩個陣列的交集 II
便捷的交換方向..
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
if (nums1.size() > nums2.size()) {
return intersect(nums2, nums1);
}
}
正解:小的進um, 大的命中直接 --
;
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { if(nums1.size()>nums2.size())return intersect(nums2, nums1); unordered_map<int,int> um; for(auto i:nums1) um[i]++; vector<int> res; for(auto i:nums2){ if(um.count(i)) { res.push_back(i),um[i]--; if(um[i]==0) um.erase(i); } } return res; }
我的
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { unordered_map<int,int> um1,um2; for(auto i:nums1) um1[i]++; for(auto i:nums2) um2[i]++; vector<int> res; for(auto i:um1){ int cnt = min(i.second, um2[i.first]); while(cnt--) res.push_back(i.first); } return res; }
434. 字串中的單詞數
int countSegments(string s) {
int ans = 0;
s += ' '; //方便分解單詞.
for (int i = 1; i < s.size(); i++)
if (s[i] == ' ' && s[i - 1] != ' ') ans++; //如果有的話.
return ans;
}
387. 字串中的第一個唯一字元
簡單解法: O(2n)
高效一點: 雜湊表直接存索引 O(n+26)
int firstUniqChar(string s) {
vector<int> um(26);
int res = INT_MAX;
for(int i =0;i<s.size();i++){
if(!um[s[i]-'a']) um[s[i]-'a'] = i+1;
else um[s[i]-'a'] = -1;
}
for(auto i:um){
if(i>0) res=min(res,i);
}
return res==INT_MAX?-1:res-1;
}
155. 最小棧
//兩個數的棧.
stack<int> s;
stack<int> smin;
MinStack() {
smin.push(INT_MAX); //輸入max可以方便底下的min比較.
}
void push(int val) {
s.push(val);
smin.push(min(val,smin.top()));
}
void pop() {
s.pop();smin.pop();
}
int top() {
return s.top();
}
int getMin() {
return smin.top();
}
//原始解法, 相當於三個數的棧.
stack<int> s1;
stack<pair<int,int>> s2;
int minval = 0,mincnt = 0;
MinStack() {}
void push(int val) {
if(!s2.empty()) minval=s2.top().first,mincnt=s2.top().second;
if(s1.size()==0 || minval >val) minval = val,mincnt = 1;
else if(minval == val) mincnt++;
s1.push(val);
s2.push({minval,mincnt});
}
void pop() {
s1.pop();
s2.pop();
}
int top() {
return s1.top();
}
int getMin() {
return s2.top().first;
}
453. 最小操作次數使陣列元素相等
其實每次n-1
個元素+1 就是最大的元素-1;
int minMoves(vector<int>& a) {
int min = *min_element(a.begin(),a.end());
int res = 0;
for(auto i:a) res+=i-min;
return res;
}
733. 影象渲染
BFS的框架.
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
vector<vector<int>> dir={{1,0},{-1,0},{0,1},{0,-1}};
queue<pair<int,int>> s;
int n = image.size(), m = image[0].size();
s.push({sr,sc});
int origin = image[sr][sc];
if(color==origin) return image; //注意... 非常重要.
while(!s.empty()){
image[s.front().first][s.front().second] = color;
for(auto i:dir){
auto x = s.front().first + i[0],y = s.front().second + i[1];
if(x>=0 && x<n && y>=0 && y<m && image[x][y] == origin){
s.push({x,y});
}
}
s.pop();
}
return image;
}
234. 迴文連結串列
如何O(n) , O(1) 也不簡單..
bool isPalindrome(ListNode* head) {
if(!head->next) return true; //單一節點, 對.
ListNode* slow = head, *fast = head;
while(fast->next && fast->next->next){
fast = fast->next->next;
slow = slow->next;
}
ListNode* hh = slow->next;
slow->next = NULL;
ListNode* newhead = NULL;
while(hh){ //反轉連結串列.
auto oldNext = hh->next;
hh->next = newhead;
newhead = hh;
hh = oldNext;
}
while(newhead){ //需要注意 後半段是一定比前半段短...
if(head->val!=newhead->val) return false;
head = head->next, newhead = newhead->next;
}
return true;
}
705. 設計雜湊集合
瞭解下如何使用 bitset
class MyHashSet {
public:
bitset<1000005> hashSet;
MyHashSet() { }
void add(int key) {
hashSet[key] = 1;
}
void remove(int key) {
hashSet[key] = 0;
}
bool contains(int key) {
return hashSet.test(key);
}
};
414. 第三大的數
使用有序集合, 如果大於最小的就抹去最小的.
int thirdMax(vector<int>& nums) {
set<int> s;
for(auto i:nums){
if(s.count(i))continue;
s.insert(i);
if(s.size()>3) s.erase(s.begin());
}
return s.size()==3?*s.begin():*s.rbegin(); //注意是 rbegin()是返回最大的.
}
// 原本 模擬法 容易出錯.
int thirdMax(vector<int>& nums) {
long long a=LONG_MIN,b=LONG_MIN,c=LONG_MIN;
for(auto i:nums){
if(i==b||i==a)continue;;
if(i>c) {
c = i;
if(c>b){
swap(c,b);
if(b>a)
swap(a,b);
}
}
}
return c!=LONG_MIN?c:a;
}
326. 3 的冪
其實可以直接判斷是否是最大的約數..
bool isPowerOfThree(int n) {
while(n && n%3==0){
n/=3;
}
return n == 1;
}
// O(1)
bool isPowerOfThree(int n) {
return n > 0 && 1162261467 % n == 0;
}
//我的
bool isPowerOfThree(int n) {
if(n<=0) return false;
n = abs(n);
while(n>1){
if(n%3) return false;
n/=3;
}
return true;;
}
506. 相對名次
vector<string> findRelativeRanks(vector<int>& score) {
int n = score.size();
vector<string> gold = {"Gold Medal","Silver Medal","Bronze Medal"};
vector<pair<int,int>> arr;
for(int i = 0;i<n; i++){
arr.emplace_back(make_pair(-score[i],i));
} // 這樣子直接放一起排序, 可以保持原有的序號, 知道哪個下標排第幾.
// emplace_back 和 make_pair好像可以加快速度?
sort(arr.begin(),arr.end());
vector<string> ans(n);
for(int i = 0;i<n;i++){
ans[arr[i].second] = i>2?to_string(i+1):gold[i];
}
return ans;
}
// 原始.
vector<string> findRelativeRanks(vector<int>& score) {
int n = score.size();
vector<int> origin = score;
sort(score.begin(), score.end());
unordered_map<int, string> um;
vector<string> gold = {"","Gold Medal","Silver Medal","Bronze Medal"};
vector<string> res;
for(int i = 0; i < n;i++){
um[score[i]] = n-i<=3?gold[n-i]:to_string(n-i);
}
for(auto i:origin){
res.push_back(um[i]);
}
return res;
}
劍指 Offer 11. 旋轉陣列的最小數字 //todo
這題意思是對旋轉陣列做二分..
劍指 Offer 42. 連續子陣列的最大和
腦筋急轉彎, 還有分治的做法. 其實就是如果前一個數最大小於0 就不要他了.
int maxSubArray(vector<int>& nums) {
int pre = 0, maxAns = nums[0];
for (const auto &x: nums) {
pre = max(pre + x, x);
maxAns = max(maxAns, pre);
}
return maxAns;
}
劍指 Offer 10- I. 斐波那契數列\todo
矩陣快速冪的方法.
面試題 10.01. 合併排序的陣列
雙指標題目, 歸併排序的模板.
void merge(vector<int>& A, int m, vector<int>& B, int n) {
int a = m - 1, b= n - 1;
for(int i = a+b+1;i>=0 ;i--){
if(a<0||b<0) A[i]=a>=0?A[a--]:B[b--];
else if(A[a] >= B[b]) A[i] = A[a--];
else A[i] = B[b--];
}
}
258. 各位相加\todo
有O(1)的解法.
290. 單詞規律
bool wordPattern(string pattern, string s) {
unordered_map<char,string> um;
unordered_map<string,char> um2;
int l = 0, len = 0;
for(int i = 0;i<pattern.size();i++){
while(l+len<s.size()&&s[l+len]!=' ') len++;
if(l>s.size()) return false;
string ss = s.substr(l,len);
char c = pattern[i];
//---------------------
if(um.count(c)^um2.count(ss)) return false;
if(um.count(c)){
if(um[c]!=ss || um2[ss]!=c) return false;
}
else um[c] = ss, um2[ss] = c;
//--------------------------上面的改成下面好一點...
if (str2ch.count(tmp) && str2ch[tmp] != ch) return false;
if (ch2str.count(ch) && ch2str[ch] != tmp) return false;
str2ch[tmp] = ch; ch2str[ch] = tmp;
//------------------------
l = l+len+1, len = 0;
}
return l>=s.size();
}
605. 種花問題
有個跳格子解法, 可是不知道其他地方能用到不.
448. 找到所有陣列中消失的數字
有個O(1)的原地操作解法
405. 數字轉換為十六進位制數
補碼是 原碼取反再加一.
string toHex(int num) {
if(num == 0) return "0"; // 避免出現先導0
string res = "";
for(int i = 7;i>=0;i--){
int c = (num>>(4*i)) & 0xf; //這裡記住是左移 4 * i 位.
if(res.size()>0 || c!=0){
res+= c<=9?'0'+c:'a'+c-10; // 這裡是
}
// cout<<c<<' ';
}
return res;
}