Commit 6c287fe4 authored by yaozc's avatar yaozc
Browse files

keep going

parent e489b9cb
......@@ -1705,83 +1705,511 @@ public:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
if (amount<0) return -1;
return helper(amount, coins, vector<int>(amount+1, 0));
}
int helper(int used_num, int residious, vector<int>& coins){
if(residious ==0) return 0;
if(residious < 0) return -1;
int helper(int remainder, vector<int>& coins, vector<int> dp){
if(remainder == 0) return 0;
if(remainder < 0 ) return -1;
else{
int min_coins = INT_MAX;
for(int i=0; i<coins.size(); i++){
if(coins[i] <= residious){
int need_coins = used_num+1;
if (helper(used_num+1, residious-coins[i], coins) != -1 ){
if(dp[remainder] != 0) return dp[remainder];
}
}
}
int min_needed = INT_MAX;
for(auto &coin: coins){
int result = helper(remainder-coin, coins, dp);
if (result != -1 && result < min_needed) min_needed = result;
}
if (min_needed != INT_MAX) dp[remainder] = min_needed+1;
else dp[remainder] = -1;
return dp[remainder];
}
};
public class Solution {
public int coinChange(int[] coins, int amount) {
return coinChange(0, coins, amount);
LRU Cache
// Design problem, the idea is a double linked list with a hash-table to record the pos of each node
class LRUCache {
private:
// key, value
list<pair<int, int>> mylist;
// key, list iterator
unordered_map<int, list<pair<int, int>>::iterator> map;
int max_capacity;
int current_capacity = 0;
public:
LRUCache(int capacity) {
max_capacity = capacity;
}
int get(int key) {
cout<<key<<endl;
auto it = map.find(key);
if(it == map.end()) {return -1;}
int element = (*(it->second)).second;
auto finder = map[key];
mylist.erase(finder);
mylist.push_front(make_pair(key, element));
map[key] = mylist.begin();
return element;
}
void put(int key, int value) {
if(map.find(key) != map.end()){
auto victim = map[key];
mylist.erase(victim);
mylist.push_front(make_pair(key, value));
map[key] = mylist.begin();
return;
}
mylist.push_front(make_pair(key, value));
map[key] = mylist.begin();
if(++current_capacity > max_capacity){
int delete_key = (mylist.back()).first;
map.erase(delete_key);
mylist.pop_back();
current_capacity = max_capacity;
}
}
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache* obj = new LRUCache(capacity);
* int param_1 = obj->get(key);
* obj->put(key,value);
*/
private int coinChange(int idxCoin, int[] coins, int amount) {
if (amount == 0)
return 0;
if (idxCoin < coins.length && amount > 0) {
int maxVal = amount/coins[idxCoin];
int minCost = Integer.MAX_VALUE;
for (int x = 0; x <= maxVal; x++) {
if (amount >= x * coins[idxCoin]) {
int res = coinChange(idxCoin + 1, coins, amount - x * coins[idxCoin]);
if (res != -1)
minCost = Math.min(minCost, res + x);
}
}
return (minCost == Integer.MAX_VALUE)? -1: minCost;
}
Min Stack
// real clean solution, 要知道stack只care之前
class MinStack {
public:
//stack which has vector in it: [0] is value in this pos, [1] is min so far
stack<vector<int>> s;
/** initialize your data structure here. */
MinStack() {
return;
}
void push(int x) {
vector<int> temp;
temp.push_back(x);
if(s.empty()) temp.push_back(x);
else{
int min = getMin();
if(min > x) min = x;
temp.push_back(min);
}
s.push(temp);
}
void pop() {
s.pop();
}
int top() {
return s.top()[0];
}
int getMin() {
return s.top()[1];
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
Find Median from data stream
//用两个priority_queue来实现median
//具体方法为:一个min heap, 一个max heap, 分别比较两边的top 后push上去
//图解如下
/*
_- Median -_
_- -_
*/
class MedianFinder {
public:
priority_queue<int, vector<int>, less<int>> max_heap;
priority_queue<int, vector<int>, greater<int>> min_heap;//upper
/** initialize your data structure here. */
MedianFinder() {
max_heap.push(INT_MIN);
min_heap.push(INT_MAX);
return;
}
void addNum(int num) {
if(num >= min_heap.top()) min_heap.push(num);
else{max_heap.push(num);}
if(max_heap.size() - min_heap.size() == 2){
min_heap.push(max_heap.top());
max_heap.pop();
}
else if(min_heap.size() - max_heap.size() == 2){
max_heap.push(min_heap.top());
min_heap.pop();
}
}
double findMedian() {
if(min_heap.size() == max_heap.size()){
return (double(min_heap.top()) + double(max_heap.top())) / 2;
}
else{
if(max_heap.size() > min_heap.size()) return max_heap.top();
return min_heap.top();
}
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/
Design Tic-Tac-Toe
//这设计实在是太聪明了。。。
//与其使用O^2的遍历table的方法,此方法实则为计分模式。player1就加1,player2就-1
//move最后check一下,分数等于n(棋盘大小)时候就赢
//就是在diag问题是我还是有点模糊,好像只需要考虑两条主对称轴情况
class TicTacToe {
public:
vector<int> cols;
vector<int> rows;
int diag = 0;
int anti_diag = 0;
/** Initialize your data structure here. */
TicTacToe(int n) {
cols = vector<int>(n, 0);
rows = vector<int>(n, 0);
}
/** Player {player} makes a move at ({row}, {col}).
@param row The row of the board.
@param col The column of the board.
@param player The player, can be either 1 or 2.
@return The current winning condition, can be either:
0: No one wins.
1: Player 1 wins.
2: Player 2 wins. */
int move(int row, int col, int player) {
int add_num = player == 1 ? 1 : -1;
int n = cols.size();
cols[col] += add_num;
rows[row] += add_num;
if(row == col) diag += add_num;
if(row + col == n - 1) anti_diag += add_num;
if(abs(cols[col]) == n || abs(rows[row]) == n ||
abs(diag) == n || abs(anti_diag) == n){
if (add_num == 1) return 1;
return 2;
}
return 0;
}
};
/**
* Your TicTacToe object will be instantiated and called as such:
* TicTacToe* obj = new TicTacToe(n);
* int param_1 = obj->move(row,col,player);
*/
Maximum Frequency Stack
//这题的data structure设计实在是太特殊了。。。
//一个vector of stack, vector中的index代表了这个元素出现的次数,相同次数的元素又都因为stack而保持了相对位置
//这设计太绝了,只能记住这种设计了吧
class FreqStack {
public:
unordered_map<int, int> hash;
vector<stack<int>> container;
FreqStack() {
stack<int> a;
}
void push(int x) {
int pos = ++hash[x];
if(pos > container.size()){
stack<int> temp;
temp.push(x);
container.push_back(temp);
}
else{container[pos-1].push(x);}
}
int pop() {
for(int i=container.size()-1; i>=0; i--){
if(!container[i].empty()){
int result = container[i].top();
container[i].pop();
hash[result]--;
return result;
}
}
return -1;
}
}
}
};
/**
* Your FreqStack object will be instantiated and called as such:
* FreqStack* obj = new FreqStack();
* obj->push(x);
* int param_2 = obj->pop();
*/
public class Solution {
public int coinChange(int[] coins, int amount) {
if (amount < 1) return 0;
return coinChange(coins, amount, new int[amount]);
Reverse Integer
//反正就一位一位填呗,做过这题就知道了
//要注意INT_MIN = INT_MAX-1
class Solution {
public:
int reverse(int x) {
bool negative = false;
if(x == INT_MIN) return 0;
if(x<0) {negative = true; x = -1 * x;}
double result = 0;
while(x>0){
result = 10* result + x%10;
x /= 10;
}
if(result > INT_MAX) return 0;
if(negative) result *= -1;
return result;
}
};
private int coinChange(int[] coins, int rem, int[] count) {
if (rem < 0) return -1;
if (rem == 0) return 0;
if (count[rem - 1] != 0) return count[rem - 1];
int min = Integer.MAX_VALUE;
for (int coin : coins) {
int res = coinChange(coins, rem - coin, count);
if (res >= 0 && res < min)
min = 1 + res;
Longest Substring Without Repeating Characters
//sliding window, 都是这类问题通解,不过这道题的remove部分有点蹊跷,我的不是标答的最优解但很容易理解
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size() == 0 || s.size() == 1) return s.size();
unordered_set<char> hash;
int left = 0;
int right = 1;
int result = 0;
hash.insert(s[0]);
while(right != s.size()){
if(hash.find(s[right]) != hash.end()){
while(s[left] != s[right]){
hash.erase(s[left]);
left++;
}
hash.erase(s[left]);
left++;
}
result = std::max(right-left+1, result);
hash.insert(s[right]);
right++;
}
count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
return count[rem - 1];
return result;
}
}
};
3SUM
//和2sum使用map的想法不同,3sum本质上其实是slidling window的问题
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size() < 3) return res;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size()-2; i++){
int left = i+1;
int right = nums.size()-1;
int current = nums[i];
while(right>left){
int temp = current + nums[left] + nums[right];
if(temp > 0){
right--;
}
else if(temp < 0){
left++;
}
else{
vector<int> temp{nums[i], nums[left], nums[right]};
res.push_back(temp);
while(left+1 < nums.size() && nums[left]==nums[left+1]) left++;
while(right-1 > 1 && nums[right] == nums[right-1]) right--;
left++;
right--;
}
}
while(nums[i] == nums[i+1] && i<nums.size()-2) i++;
}
return res;
}
};
Remove Duplicates from Sorted Array
//这题鬼的很。。。很容易想多。。但其实答案很简单.....
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 1 || nums.size() == 0) return nums.size();
int left = 0;
for(int right=1; right<nums.size(); right++){
if(nums[left] != nums[right]){
left++;
nums[left] = nums[right];
}
}
return left+1;
}
};
//
Roman to Integer
//easy,反正每次读到小的在前,大的在后就当一个comb来看就行了
class Solution {
public:
int romanToInt(string s) {
unordered_map<char, int>hash{ {'I',1}, {'V',5}, {'X',10}, {'L',50}, {'C',100}, {'D',500}, {'M',1000} };
bool last_used = true;
int sum = 0;
for(int i=0; i<s.size()-1; i++){
if(hash[s[i]] < hash[s[i+1]]){
if(i == s.size()-2) last_used = false;
sum += hash[s[i+1]] - hash[s[i]];
i++;
}
else sum += hash[s[i]];
}
if(last_used) {sum += hash[s[s.size()-1]];}
return sum;
}
};
Minimum Window Substring
//典型的 String window substring sliding 问题,很值得参考,尤其是查找substring是否contain string T中所有字符的那段,
//方法为使用两个hash table,然后每符合一个就给var current_match_num+1,直到 current_match_num == need_match_num,就是
//所有substrig match的时候
class Solution {
public:
string minWindow(string s, string t) {
if(s.size()==0 || t.size()==0) return "";
if(s.size()==1 && t != s) return "";
if(t == s) return t;
unordered_map<char, int>hash_t;
for(auto &k:t) hash_t[k] += 1;
int need_match_num = hash_t.size(), current_match_num = 0;
int left = 0, right = 0, min_length = INT_MAX, min_left = 0, min_right = 0;
unordered_map<char, int>hash_s;
while(right<s.size()){
hash_s[s[right]] += 1;
if(hash_t.find(s[right])!=hash_t.end() && hash_s[s[right]] == hash_t[s[right]]) current_match_num++;
while(need_match_num == current_match_num){
if(right-left+1 < min_length){
min_length = right-left+1;
min_left = left;
min_right = right;
}
--hash_s[s[left]];
if(hash_t.find(s[left])!=hash_t.end() && hash_s[s[left]] < hash_t[s[left]]){
current_match_num--;
}
left++;
}
right++;
}
return min_length != INT_MAX ? s.substr(min_left, min_length) : "";
}
};
Valid Palindrome
//这题奇奇怪怪的test case也太鬼了。。。。这个if else的写法真的是一开始没想到(本来是while里套while的)
class Solution {
public:
bool isPalindrome(string s) {
if(s.size()<=1) return true;
int left = 0, right = s.size()-1;
while(left <= right){
if(!isalnum(s[left])) {left++;}
else if(!isalnum(s[right])){right--;}
else if(toupper(s[left]) == toupper(s[right])){
left++;
right--;
}
else return false;
}
return true;
}
};
Subarray Sum Equals K
//使用hash table来记录 到之前所有index位置的 sum的总和
//非常经典的一道题,很值得研究
//其他几种方法均为brutal force
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
// <culumative_sum, nums>
unordered_map<int, int> hash;
int sum = 0;
int res = 0;
hash[0] = 1;
for(int i=0; i<nums.size(); i++){
//cout<<i<<endl;
sum += nums[i];
int left_over = sum - k;
// found left_over in the hash_table?
// it means that without the found part(subarray)
// the sum of current subarray == k
if(hash.find(left_over) != hash.end()){
res += hash[left_over];
}
hash[sum]++;
}
return res;
}
};
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment