3. 无重复字符的最长子串
滑动窗口
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> uset;
int n = s.size();
int left = 0;
int right = 0;
int result = 0;
int tmp;
while(right < n)
{
if(uset.find(s[right]) == uset.end())
{
uset.insert(s[right]);
right++;
}else
{
uset.erase(s[left]);
left++;
}
result = max(result,right-left);
}
return result;
}
};
双指针法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* tmp;
while(cur)
{
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> pg;
vector<int> vec(nums.size(),0);
for(int i = 0; i < nums.size() ; i++)
{
pg.push(-nums[i]);
if(pg.size() > k)
{
pg.pop();
}
}
int ret = -pg.top();
return ret;
}
};
priority_queue<int> pg(优先队列)默认是大顶堆,所以在push的时候取反,就变成了小顶堆,然后就往里面添加,当当前堆大小大于k,就输出(就是把当前最小的输出出去)
方法一,用栈,k个k个为一组,先入栈再出栈
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* cur = head;
int count = 0;
while(cur)
{
count++;
cur = cur->next;
}
ListNode* result = new ListNode(0);
result->next = head;
ListNode* pre = result;
ListNode* tmp;
ListNode* mid;
cur = head;
stack<ListNode*> st;
for(int i = 0; i < count/k; i++)
{
int j = 0;
while(j < k)
{
st.push(cur);
cur = cur->next;
j++;
}
mid = cur;
j = 0;
while(j < k)
{
tmp = st.top();
st.pop();
pre->next = tmp;
pre = tmp;
j++;
}
pre->next = cur;
}
return result->next;
}
};
方法二,使用反转链表,找到k区间内的第一个和最后一个,然后翻转完,原来的头就是新的尾,原来的尾就是新的头,然后给连接起来就行
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reverse(ListNode* head,ListNode* tail){
ListNode* cur = head;
ListNode* tmp;
ListNode* pre = nullptr;
while(pre != tail)
{
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* result = new ListNode(0);
ListNode* pre = result;
ListNode* tail;
while(head)
{
tail = head;
for(int i = 1; i < k; i++)
{
tail = tail->next;
if(tail == nullptr)
{
pre->next = head;
return result->next;
}
}
ListNode* next = tail->next; // 需保存下一段头节点用于后续翻转
reverse(head,tail); // reverse 之后 newHead = tail, newTail = head
pre->next = tail; // 将前一段与当前段连接,并移到下一段准备翻转
pre = head;
head = next;
}
return result->next;
}
};
方法一(回溯算法):
超时了 阿西。。。
class Solution {
public:
vector<vector<int>> result;
void backtracking(vector<int> cur,vector<int> nums,int startIndex,int sum)
{
if(cur.size() == 3 && sum == 0)
{
result.push_back(cur);
return;
}
for(int i = startIndex; i < nums.size(); i++)
{
if(i > startIndex && nums[i] == nums[i-1])
{
continue;
}else
{
sum += nums[i];
cur.push_back(nums[i]);
backtracking(cur,nums,i+1,sum);
sum -= nums[i];
cur.pop_back();
}
}
}
vector<vector<int>> threeSum(vector<int>& nums) {
result.clear();
vector<int> cur;
sort(nums.begin(),nums.end());
backtracking(cur,nums,0,0);
return result;
}
};
时间复杂度:O(n*2^n)
方法二(双指针)
class Solution {
public:
vector<vector<int>> result;
vector<vector<int>> threeSum(vector<int>& nums) {
result.clear();
vector<int> cur;
sort(nums.begin(),nums.end());
for(int i = 0 ; i < nums.size(); i++)
{
if(nums[i] > 0)
return result;
if(i > 0&& nums[i] == nums[i-1])
{
continue;
}else
{
int left = i+1;
int right = nums.size()-1;
while(right > left)
{
if(nums[i] + nums[left] + nums[right] == 0)
{
result.push_back(vector<int>{nums[i],nums[left],nums[right]});
while(right > left && nums[right] == nums[right - 1])
{
right--;
}
while(right > left && nums[left] == nums[left +1])
{
left++;
}
left++;
right--;
}else if(nums[i] + nums[left] + nums[right] > 0)
{
right--;
}else if(nums[i] + nums[left] + nums[right] < 0)
{
left++;
}
}
}
}
return result;
}
};
时间复杂度:O(N^2)
如果某一问题有很多重叠子问题,使用动态规划,每一个状态一定是由上一个状态推导出来的
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size(),0);
dp[0] = nums[0];
int result = dp[0];
if(nums.size() == 1)
return nums[0];
for(int i = 1; i < nums.size(); i++)
{
dp[i] = max(dp[i-1]+nums[i],nums[i]);
if(dp[i] > result)
result = dp[i];
}
return result;
}
};
冒泡排序:
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
for(int i = 0; i < nums.size(); i++)
{
bool flag = true;
for(int j = nums.size()-1; j > 0; j--)
{
if(nums[j] < nums[j-1])
{
swap(nums[j],nums[j-1]);
flag = false;
}
}
if(flag)
break;
}
return nums;
}
};
插入排序
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
for(int i = 1; i < nums.size(); i++)
{
int tmp = nums[i];
int j = i-1;
while(j >= 0 && tmp < nums[j])
{
nums[j+1] = nums[j];
j--;
}
nums[j+1] = tmp;
}
return nums;
}
};
快速排序,要用到递归
class Solution {
public:
int position(vector<int> &nums,int left,int right)
{
int pivot = nums[left];
int i = left;
int j = right;
while(i < j)
{
while(i < j && nums[j] >= pivot)
j--;
nums[i] = nums[j];
while(i < j && nums[i] <= pivot)
i++;
nums[j] = nums[i];
}
nums[i] = pivot;
return i;
}
void QuickSort(vector<int> &nums,int left,int right)
{
if(left < right)
{
int pivot = position(nums,left,right);
QuickSort(nums,left,pivot-1);
QuickSort(nums,pivot+1,right);
}
}
vector<int> sortArray(vector<int>& nums) {
QuickSort(nums,0,nums.size()-1);
return nums;
}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* result = new ListNode(0);
ListNode* head = new ListNode(0);
result = head;
while(list2 && list1)
{
while(list2 && list1 && list1->val <= list2->val)
{
head->next = list1;
head = head->next;
list1 = list1->next;
}
while(list2 && list1 && list1->val > list2->val)
{
head->next = list2;
head = head->next;
list2 = list2->next;
}
}
if(list2)
head->next = list2;
if(list1)
head->next = list1;
return result->next;
}
};
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> unmap;
for(int i = 0; i < nums.size(); i++)
{
unmap.insert(pair<int,int>(nums[i],i));
}
vector<int> result;
for(int i = 0; i < nums.size(); i++)
{
int tmp = nums[i];
int cur = target-tmp;
if(unmap.find(cur) != unmap.end())
{
auto index = unmap.find(cur);
if(index->second == i)
continue;
else
{
result.push_back(i);
result.push_back(index->second);
return result;
}
}
}
return result;
}
};
unorder_map添加要用insert
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> result;
if(root == nullptr)
return result;
que.push(root);
int size;
vector<int> eve;
TreeNode* tmp;
while(!que.empty())
{
size = que.size();
eve.clear();
while(size > 0)
{
tmp = que.front();
que.pop();
eve.push_back(tmp->val);
size--;
if(tmp->left)
que.push(tmp->left);
if(tmp->right)
que.push(tmp->right);
}
result.push_back(eve);
}
return result;
}
};
动态规划:
class Solution {
public:
string longestPalindrome(string s) {
vector<vector<bool>> dp(s.size(),vector<bool>(s.size(),false));
int maxlength = 0;
int left = 0;
int right = 0;
for(int i = s.size()-1; i >=0; i--)
{
for(int j = i; j < s.size(); j++)
{
if(s[i] == s[j])
{
if(j-i <= 1)
{
dp[i][j] = true;
}else if(dp[i+1][j-1])
{
dp[i][j] = true;
}
}
if(dp[i][j] && j-i+1 > maxlength)
{
maxlength = j - i + 1;
left = i;
right = j;
}
}
}
return s.substr(left,right-left+1);
}
};
class Solution {
public:
int search(vector<int>& nums, int target) {
int right = nums.size()-1;
int left = 0;
int mid;
while(left <= right)
{
mid = (left + right)/2;
if(nums[mid] == target)
return mid;
if(nums[mid] < nums[right])
{
if(nums[mid] < target && target <= nums[right])
left = mid+1;
else
{
right = mid-1;
}
}else
{
if(nums[left] <= target && target < nums[mid])
right = mid-1;
else
left = mid+1;
}
}
return -1;
}
};
class Solution {
public:
bool isValid(string s) {
stack<char> st;
int i = 0;
while(s[i] != '\0')
{
if(s[i] == '(' || s[i] == '{' || s[i] == '[')
st.push(s[i]);
else
{
if(st.empty())
return false;
if(s[i] == ')' && st.top() == '(')
st.pop();
else if(s[i] == '}' && st.top() == '{')
st.pop();
else if(s[i] == ']' && st.top() == '[')
st.pop();
else
return false;
}
i++;
}
if(st.empty())
return true;
else
return false;
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(),vector<int>(2,0));//0:买入 1:维持住
dp[0][0] = -prices[0];
dp[0][1] = 0;
int result = 0;
for(int i = 1; i < prices.size(); i++)
{
dp[i][0] = max(-prices[i],dp[i-1][0]);
dp[i][1] = max(prices[i] + dp[i-1][0],dp[i-1][1]);
if(dp[i][1] > result)
result = dp[i][1];
}
return result;
}
};
分两种情况:买入和维持住,买入的话比较当前买入好还是前一天买入好,维持的话是比较卖掉好,还是保持之前的情况好
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast && slow)
{
slow = slow->next;
if(fast->next)
{
fast = fast->next->next;
}else
return false;
if(fast == slow)
return true;
}
return false;
}
};
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m+n-1;
m = m-1;
n = n-1;
while(m >=0 && n >= 0)
{
if(nums1[m] < nums2[n])
{
nums1[i] = nums2[n];
n--;
}
else
{
nums1[i] = nums1[m];
m--;
}
i--;
}
while(n >= 0)
{
nums1[i] = nums2[n];
i--;
n--;
}
return;
}
};
class LRUCache {
// private Map<int,int> lruCache = new LinkedHashMap<>();
private:
int capacity;
list<pair<int, int>> cache; < @note pair[key]=value
unordered_map<int, list<pair<int, int>>::iterator> lruCache;
public:
LRUCache(int capacity) {
this->capacity = capacity;
}
int get(int key) {
if(lruCache.find(key) != lruCache.end())
{
pair<int,int> node = *lruCache[key];
cache.erase(lruCache[key]);
cache.push_front(node);
lruCache[key] = cache.begin();
return node.second;
}else
return -1;
}
void put(int key, int value) {
auto newNode = std::make_pair(key, value);
if(lruCache.find(key) != lruCache.end())
{
cache.erase(lruCache[key]);
}else if(cache.size() == capacity)
{
lruCache.erase(cache.back().first);
cache.pop_back();
}
cache.push_front(newNode);
lruCache[key] = cache.begin();
return;
}
};
/**
* 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);
*/
C++的写法是unordered_map和list相结合啊啊啊
class Solution {
public:
void DFS(vector<vector<char>>& grid,int i,int j,int row,int col)
{
// used[i][j] = 1;
grid[i][j] = '0';
if (i - 1 >= 0 && grid[i-1][j] == '1') DFS(grid, i - 1, j,row,col);
if (i + 1 < row && grid[i+1][j] == '1') DFS(grid, i + 1, j,row,col);
if (j - 1 >= 0 && grid[i][j-1] == '1') DFS(grid, i, j - 1,row,col);
if (j + 1 < col && grid[i][j+1] == '1') DFS(grid, i, j + 1,row,col);
return;
}
int numIslands(vector<vector<char>>& grid) {
int row = grid.size();
int col = grid.front().size();
// vector<vector<int>> used(row,vector<int>(col,0)); //0:未使用 1:已使用
int num = 0;
for(int i = 0 ; i < row ; i++)
{
for(int j = 0; j < col; j++)
{
if(grid[i][j] == '0' )
continue;
else
{
DFS(grid,i,j,row,col);
num++;
}
}
}
return num;
}
};
只要是有1就说明有岛,找到岛的边界,并把岛上的位置都设为0,防止重复找。
class Solution {
public:
TreeNode* result;
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || root == p || root == q)
{
return root;
}
TreeNode* left = lowestCommonAncestor(root->left,p,q);
TreeNode* right = lowestCommonAncestor(root->right,p,q);
if(left && right)
return root;
if(left)
return left;
if(right)
return right;
return NULL;
}
};