递归法:
class Solution {
public:
bool check(TreeNode *p, TreeNode *q) {
if (!p && !q) return true;
if (!p || !q) return false;
return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
迭代法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue Q;
Q.push(root);
Q.push(root);
TreeNode *p,*q;
while(!Q.empty()){
p=Q.front();
Q.pop();
q=Q.front();
Q.pop();
if(!p&&!q){
continue;
}
if( (!p || !q)||(p->val!=q->val)){
return false;
}
Q.push(p->left);
Q.push(q->right);
Q.push(p->right);
Q.push(q->left);
}
return true;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector> levelOrder(TreeNode* root) {
if(root==NULL){
return {};
}
vector> result;
vector temp;
queue> Q;
Q.push(make_pair(root,1));
int last=1;
while(!Q.empty()){
TreeNode* node=Q.front().first;
int depth=Q.front().second;
if(last==depth){
temp.push_back(node->val);
}
else{
result.push_back(temp);
temp.clear();
temp.push_back(node->val);
}
last=depth;
Q.pop();
if(node->left)
Q.push(make_pair(node->left,depth+1));
if(node->right)
Q.push(make_pair(node->right,depth+1));
}
result.push_back(temp);
return result;
}
};
这道题面试时遇到了原题,当时我是用一个queue一个stack解决的,但这次刷到发现可以用一个dequeue节省空间复杂度!
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector> zigzagLevelOrder(TreeNode* root) {
if(root==NULL) return {};
vector> result;
deque Q;
Q.push_front(root);
//是否是奇数行
bool isOdd=true;
while(!Q.empty()){
vector layer;
//每次直接把这一层的都执行完
for(int i=Q.size()-1;i>=0;i--){
TreeNode *cur;
//奇数行从前往后取节点,孩子从左向右进队尾
if(isOdd){
cur =Q.front();Q.pop_front();
layer.push_back(cur->val);
if(cur->left) Q.push_back(cur->left);
if(cur->right) Q.push_back(cur->right);
}
else{//偶数行从后往前取节点,孩子从右向左进队首
cur=Q.back();Q.pop_back();
layer.push_back(cur->val);
if(cur->right) Q.push_front(cur->right);
if(cur->left) Q.push_front(cur->left);
}
}
//每一层遍历完 奇偶数交换,并把该层加入结果中
isOdd=!isOdd;
result.push_back(layer);
}
return result;
}
};
怎么遍历都可以,我写了个递归的深搜
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL){
return 0;
}
int ldepth=maxDepth(root->left);
int rdepth=maxDepth(root->right);
return (max(ldepth,rdepth)+1) ;
}
};
自己写了一个用递归,但速度和内存消耗都不太理想!!
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector& preorder, vector& inorder) {
int m=preorder.size();
if(m==0) return NULL;
//根就是先根序遍历得根
TreeNode* root=new TreeNode(preorder[0]);
//定义向下传递得vector
vector preorder_left,inorder_left,preorder_right,inorder_right;
int index;
//把左右子树得中序遍历数组求好
for(index=0;indexleft=buildTree(preorder_left,inorder_left);
root->right=buildTree(preorder_right,inorder_right);
return root;
}
};
递归就好!!! 发现了嘛?只要让你构造二叉树,就很可能用递归就可以解决呦!!
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* sortedArrayToBST(vector& nums) {
return construct(nums,0,nums.size()-1);
}
TreeNode* construct(vector& nums,int left,int right){
if(left>right){
return NULL;
}
//总是选择中间位置左边数字为根
int mid=(left+right)/2;
TreeNode *root=new TreeNode(nums[mid]);
root->left=construct(nums,left,mid-1);
root->right=construct(nums,mid+1,right);
return root;
}
};
又是层次遍历的变形!!
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
if(root==NULL){
return root;
}
queue Q;
Q.push(root);
while(!Q.empty()){
int length=Q.size();
for(int i=0;ileft) Q.push(cur->left);
if(cur->right) Q.push(cur->right);
cur->next=Q.front();
}
Node* cur=Q.front();
Q.pop();
cur->next=NULL;
if(cur->left) Q.push(cur->left);
if(cur->right) Q.push(cur->right);
}
return root;
}
};
算是动态规划吧!!!
class Solution {
public:
vector> generate(int numRows) {
vector> result;
if(numRows==0){
return result;
}
result.push_back({1});
if(numRows==1){
return result;
}
for(int i=2;i<=numRows;i++){
result.push_back(vector(i,1));
for(int j=1;j
动态规划即可
class Solution {
public:
int maxProfit(vector& prices) {
if(prices.size()==0){
return 0;
}
vector dp(prices.size(),0);
int min=prices[0];
int max=prices[0];
for(int i=1;idp[i-1]){
dp[i]=prices[i]-min;
}
else{
dp[i]=dp[i-1];
}
if(prices[i]>max){
max=prices[i];
}
if(prices[i]
贪心算法
class Solution {
public:
int maxProfit(vector& prices) {
int result=0;
for(int i=1;iprices[i-1]){
result+=prices[i]-prices[i-1];
}
}
return result;
}
};
要记得 isalnum()判断是否是字母和数字,tolower()变小写这些常用的库函数
class Solution {
public:
bool isPalindrome(string s) {
if(s.size()<2){
return true;
}
int l=0;
int r=s.size()-1;
while(l
很重要的一道题,双向BFS,BFS的搜索过程是金字塔型的,随着搜索深度的增加塔基会越来越大。而使用双向BFS可以有效的优化这种问题!
// Time 68ms, 13.4MB
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector& wordList) {
//
unordered_map freqs;
for(const auto &word:wordList)
freqs[word]=0;
//压根没有目标直接返回0
if(freqs.count(endWord)==0) return 0;
//双向BFS,所以需要两个队列
queue q1({beginWord}), q2({endWord});
int step=1;
for(freqs[beginWord]|=1,freqs[endWord]|=2; q1.size() && q2.size(); ++step){
//拿到短的队列
bool first=q1.size() &q=first?q1:q2;
int flag=first?1:2;
//当前层全部搜一遍
for(int size=q.size(); size--; q.pop()){
string &word=q.front();
//相遇时停止
if(freqs[word]==3) return step;
//找下一个词
for(int i=0; i
这道题是困难难度的,因为他想考察并查集,但用哈希表来做其实不太难
class Solution {
public:
int longestConsecutive(vector& nums) {
unordered_set st;
for(int n:nums) st.insert(n);
int ans=0;
for(int i:st){
if(i!=INT_MIN && st.count(i-1)){
continue;
}
int cnt=1;
while(i!=INT_MAX && st.count(i+1)){
cnt++;
i++;
}
ans=max(ans,cnt);
}
return ans;
}
};
非常巧妙的反向思维,把搜索内部O变成从边界的O开始深搜!!!
class Solution {
public:
void solve(vector>& board) {
if(board.size()<=1 || board[0].size()<=1){
return;
}
int row=board.size();
int col=board[0].size();
for(int i=0;i> &board,int i,int j){
static const int dx[]={1,-1,0,0};
static const int dy[]={0,0,1,-1};
board[i][j]='#';
for(int k=0;k<4;k++){
int newx=dx[k]+i;
int newy=dy[k]+j;
if(newx>=0 && newx=0 && newy
这种要求返回所有可能的题目基本就是回溯法
class Solution {
vector> res;
int size;
//检查是否是回文串
bool check(const string&s, int i, int j) {
if (j < i) return true;
if (s[i++] == s[j--]) return check(s, i, j);
else return false;
}
void backtrack(const string& s, int ps, vector& temp) {
if (ps >= size) {
res.push_back(temp);
return;
}
//递归树分支:以当前ps位置为开始分割所有的回文串,后面部分递归进行处理
for (int i = ps; i < size; ++i) {
if (check(s, ps, i)) {
temp.push_back(s.substr(ps, i-ps+1));
backtrack(s, i+1, temp);
temp.pop_back();
}
}
}
public:
vector> partition(const string& s) {
size = s.size();
if (size == 0) return res;
vector temp;
backtrack(s, 0, temp);
return res;
}
};
看到要求返回最少次数之类问题,就可以考虑动态规划!!
class Solution {
public:
int minCut(string s) {
int len=s.length();
// 状态定义:dp[i]:前缀子串 s[0:i] (包括索引 i 处的字符)符合要求的最少分割次数
int dp[len];
// 1 个字符最多分割 0 次;
// 2 个字符最多分割 1 次;
// 3 个字符最多分割 2 次
// 初始化的时候,设置成为这个最多分割次数
for(int i=0;i> checkPalindrome(len, vector(len, false));
//根据所给的字符串s,遍历,记录子串s[a:b]是否为回文串
for(int right=0;right
自己写的一个会超出时间,因为判断是否是回文数的算法用的双指针,是线性时间复杂度
class Solution {
public:
int minCut(string s) {
if(s.size()<2){
return 0;
}
vector dp(s.size());
//初始化
for(int i=0;i
先判断能不能走一圈,如果能就用双指针来走一遍!!!
class Solution {
public:
int canCompleteCircuit(vector& gas, vector& cost) {
if (gas.size() == 1)
return gas[0] >= cost[0] ? 0 : -1;
int gas_sum = accumulate(gas.begin(), gas.end(),0);//0为累加的初值
int cost_sum = accumulate(cost.begin(), cost.end(), 0);
//这里进行初始判断,如果总汽油量小于总花费量直接返回-1.
if (gas_sum < cost_sum )
return -1;
int left = 0;//由于条件以满足,故left可以任意赋初值。
int right = 1;
int temp = gas[left]-cost[left];
int N=gas.size();
while (right != left)
{
if (temp >= 0)
{
//走到right处,right右移
temp += gas[right] - cost[right];
right = right == N - 1 ? 0 : right + 1;
}
else
{ //向左找加油站
left = left == 0 ? N - 1 : left - 1;//这里要先改left再加。
temp += gas[left] - cost[left];
}
}
return left;
}
};
记得位运算可以巧妙解决问题呀!!!!!!!!!!!!!
class Solution {
public:
int singleNumber(vector& nums) {
int result=0;
for(int i=0;i
只要存在映射的相对关系就可以考虑哈希表
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
map map1;
vector map2;
Node* head1=head;
if(!head1)
{
return NULL;
}
int i=0;
while(head1)
{
//新增结点
map2.push_back(new Node(head1->val));
//原链表对应关系存入map1
map1[head1]=i;
head1=head1->next;
i++;
}
head1=head;
i=0;
map2.push_back(0);
while(head1)
{
map2[i]->next=map2[i+1];
if(head1->random)
{
map2[i]->random=map2[map1[head1->random]];
}
head1=head1->next;
i++;
}
return map2[0];
}
};
不是特别容易想到的一个动态规划
class Solution {
public:
bool wordBreak(string s, vector& wordDict) {
unordered_set wordDictSet;
for(auto i:wordDict){
wordDictSet.insert(i);
}
vector dp(s.size()+1,false);
dp[0]=true;
for(int i=1;i<=s.size();i++){
for(int j=0;j
必会经典!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head){
return false;
}
ListNode *fast=head;
ListNode *slow=head;
while(fast){
fast=fast->next;
if(!fast) return false;
fast=fast->next;
slow=slow->next;
if(fast==slow){
return true;
}
}
return false;
}
};
考察数据结构能力!!自己没想出来,直接放官方代码吧
---------------题目内容--------------------------------------------------
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
//哈希双链表
struct DLinkNode{
int key,value;
DLinkNode *prev;
DLinkNode *next;
DLinkNode():key(0),value(0),prev(nullptr),next(nullptr){}
DLinkNode(int _key,int _value):key(_key),value(_value),prev(nullptr),next(nullptr){}
};
class LRUCache {
private:
unordered_map cache;
DLinkNode *head;
DLinkNode *tail;
int size;
int capacity;
public:
LRUCache(int capacity) {
this->size=0;
this->capacity=capacity;
head=new DLinkNode();
tail=new DLinkNode();
head->next=tail;
tail->prev=head;
}
int get(int key) {
//如果没有返回-1
if(!cache.count(key)){
return -1;
}
//如果有的话先拿到结点然后放到队首
DLinkNode *node=cache[key];
moveToHead(node);
return node->value;
}
void put(int key, int value) {
//如果不存在key
if(!cache.count(key)){
//创建结点
DLinkNode *node=new DLinkNode(key,value);
//添加到哈希表
cache[key]=node;
//添加至队首
addToHead(node);
size++;
//容量不够时删除队尾的元素
if(size>capacity){
DLinkNode *removed=removeTail();
//删除哈希表中的对应项
cache.erase(removed->key);
//避免内存泄漏
delete removed;
size--;
}
}
else{
//如果存在则修改value并移动到队首
DLinkNode *node=cache[key];
node->value=value;
moveToHead(node);
}
}
private:
//移除结点
void remove(DLinkNode *node){
node->next->prev=node->prev;
node->prev->next=node->next;
}
//在队首添加结点
void addToHead(DLinkNode *node){
node->prev=head;
node->next=head->next;
head->next->prev=node;
head->next=node;
}
//移动到队首
void moveToHead(DLinkNode *node){
remove(node);
addToHead(node);
}
//删除队尾结点
DLinkNode* removeTail(){
DLinkNode *removed=tail->prev;
remove(removed);
return removed;
}
};
/**
* 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);
*/
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
二路归并
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (head == NULL || head->next == NULL)
{
return head;
}
ListNode* pmid;
ListNode* mid = head;
ListNode* trail = head;
while (trail && trail->next)
{
pmid = mid;
mid = mid->next;
trail = trail->next->next;
}
pmid->next = NULL;
return twoWayMerge(sortList(head), sortList(mid));
}
ListNode* twoWayMerge(ListNode* l1, ListNode* l2) {
ListNode header(-1);
ListNode *p = &header;
while (l1 && l2)
{
if (l1->val < l2->val)
{
p->next = l1;
l1 = l1->next;
}
else
{
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p->next = l1 == NULL ? l2 : l1;
return header.next;
}
};
把求斜率的除法变成乘法
class Solution {
public:
int maxPoints(vector>& points)
{
//两点确定一条直线
const int size = points.size();
if(size<3)
return size;
int Max=0;
for(int i=0;i< size;i++)//i表示数组中的第i+1个点
{
//same用来表示和i一样的点
int same=1;
for(int j=i+1;j < size;j++)//j表示数组中的第j+1个点
{
int count=0;
// i、j在数组中是重复点,计数
if(points[i][0]==points[j][0]&&points[i][1]==points[j][1])
same++;
else//i和j不是重复点,则计算和直线ij在一条直线上的点
{
count++;
long long xDiff = (long long)(points[i][0] - points[j][0]);//Δx1
long long yDiff = (long long)(points[i][1] - points[j][1]);//Δy1
//Δy1/Δx1=Δy2/Δx2 => Δx1*Δy2=Δy1*Δx2,计算和直线ji在一条直线上的点
for (int k = j + 1; k < size; ++k)
{
if (xDiff * (points[i][1] - points[k][1]) == yDiff * (points[i][0] - points[k][0]))
count++;
}
}
Max=max(Max,same+count);
}
if(Max> size /2)
return Max;//若某次最大个数超过所有点的一半,则不可能存在其他直线通过更多的点
}
return Max;
}
};
记得可以用stringstream来直接进行atoi的操作
class Solution {
public:
int evalRPN(vector& tokens) {
if(tokens.empty()) return 0;
stack numst;
stringstream ss;
for(int i = 0;i>number;
numst.push(number);
}
}
return numst.top();
}
};
非常经典的一个动态规划思想,要借助两个动态规划数组!
class Solution {
public:
int maxProduct(vector& nums) {
vector maxDP(nums.size());
vector minDP(nums.size());
maxDP[0]=nums[0];
minDP[0]=nums[0];
int result=maxDP[0];
for(int i=1;i
class MinStack {
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
if(_data.empty())
{
_data.push(x);
_min.push(x);
return;
}
_data.push(x);
if(x<_min.top())
{
_min.push(x);
}
else
{
_min.push(_min.top());
}
}
void pop() {
_data.pop();
_min.pop();
}
int top() {
return _data.top();
}
int getMin() {
return _min.top();
}
private:
stack _data;
stack _min;
};
/**
* 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();
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lengthA=0;
int lengthB=0;
ListNode *pA=headA;
ListNode *pB=headB;
while(pA){
lengthA++;
pA=pA->next;
}
while(pB){
lengthB++;
pB=pB->next;
}
if(lengthA>lengthB){
for(int i=0;i<(lengthA-lengthB);i++){
headA=headA->next;
}
}
else if(lengthB>lengthA){
for(int i=0;i<(lengthB-lengthA);i++){
headB=headB->next;
}
}
//开始找
while(headA && headB){
if(headA==headB){
return headA;
}
headA=headA->next;
headB=headB->next;
}
return NULL;
}
};
只要遇到找某个有特点的值,优先考虑二分查找!!!
class Solution {
public:
int findPeakElement(vector& nums) {
if(nums.size()==1){
return 0;
}
return bsearch(nums,0,nums.size()-1);
}
int bsearch(vector& nums,int l,int r){
if(l==r){
return l;
}
int mid=(l+r)/2;
if(nums[mid]>nums[mid+1]){
return bsearch(nums,l,mid);
}
return bsearch(nums,mid+1,r);
}
};
这道题不难,但是有很多细节要考虑全面!!
class Solution {
public:
//小数部分如果余数重复出现两次就表示该小数是循环小数了
string fractionToDecimal(int numerator, int denominator) {
if(denominator==0) return "";//边界条件,分母为0
if(numerator==0) return "0";//边界条件,分子为0
string result;
//转换为longlong防止溢出
long long num = static_cast(numerator);
long long denom = static_cast(denominator);
//处理正负号,一正一负取负号
if((num>0)^(denom>0))result.push_back('-');
//分子分母全部转换为正数
num=llabs(num);denom=llabs(denom);
//处理整数部分
result.append(to_string(num/denom));
//处理小数部分
num%=denom; //获得余数
if(num==0)return result; //余数为0,表示整除了,直接返回结果
result.push_back('.'); //余数不为0,添加小数点
int index=result.size()-1; //获得小数点的下标
unordered_map record; //map用来记录出现重复数的下标,然后将'('插入到重复数前面就好了
while(num&&record.count(num)==0){ //小数部分:余数不为0且余数还没有出现重复数字
record[num]=++index;
num*=10; //余数扩大10倍,然后求商,和草稿本上运算方法是一样的
result+=to_string(num/denom);
num%=denom;
}
if(record.count(num)==1){ //出现循环余数,我们直接在重复数字前面添加'(',字符串末尾添加')'
result.insert(record[num],"(");
result.push_back(')');
}
return result;
}
};
class Solution {
public:
int majorityElement(vector& nums) {
unordered_map hash;
for(int i=0;i::iterator iter=hash.begin();
int result;
while(iter!=hash.end()){
if(iter->second>(nums.size()/2) ){
result=iter->first;
break;
}
else{
iter++;
}
}
return result;
}
};
class Solution {
public:
int titleToNumber(string s) {
int result=0;
int _pow=0;
for(int i=s.size()-1;i>=0;i--){
result+=pow(26,_pow)*(s[i]-'A'+1);
_pow++;
}
return result;
}
};
class Solution {
public:
int trailingZeroes(int n) {
if(n<5){
return 0;
}
return (n/5 +trailingZeroes(n/5));
}
};
class Solution {
public:
string largestNumber(vector& nums) {
if(nums.empty()) return "";
if(nums.size() == 1) return to_string(nums[0]);
sort(nums.begin(), nums.end(), cmp()); // 调用STL中的sort函数
string result = "";
for(int i : nums)
{
result += to_string(i);
}
// 特殊case,全是0的时候应该输出0而不是00000
if(result[0] == '0') return "0";
return result;
}
struct cmp{
bool operator()(const int& a, const int& b){
string concatenation1 = to_string(a) + to_string(b);
string concatenation2 = to_string(b) + to_string(a);
return concatenation1 > concatenation2;
}
};
};
虽然是道简单题,但环状替代思想还是很值得思考得!!!下面得结论很重要
对于一个长度为 n 的数组,整体移动 k 个位置
当 n 和 k 的最大公约数 等于 1 的时候:1 次遍历就可以完成交换;比如 n = 5, k = 3n=5,k=3
当 n 和 k 的最大公约数 不等于 1 的时候:1 次遍历是无法完成的所有元素归位,需要 mm (最大公约数) 次
class Solution {
public:
void rotate(vector& nums, int k) {
if(nums.size()<=1){
return;
}
int count=0;
for(int i=0;count
位运算!!
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t result=0;
int power=31;
while(n!=0){
result+=(n&1)<>1;
power--;
}
return result;
}
};
记住 n=n&(n-1)这个操作会把n最后的那个1置为0
class Solution {
public:
int hammingWeight(uint32_t n) {
int ans=0;
while(n>0){
n=n&(n-1);
ans++;
}
return ans;
}
};
动态规划
class Solution {
public:
int rob(vector& nums) {
if(nums.size() ==0 ){
return 0;
}
if(nums.size() ==1){
return nums[0];
}
vector dp(nums.size(),0);
dp[0]=nums[0];
dp[1]=std::max(nums[0],nums[1]);
for(int i=2;i
经典深搜问题
class Solution {
public:
int numIslands(vector>& grid) {
if(grid.size()==0){
return 0;
}
int result=0;
vector> mark(grid.size(),vector(grid[0].size(),0));
for(int i=0;i> &mark,
std::vector>& grid,int x,int y ){
static const int dx[] ={-1,1,0,0};
static const int dy[] ={0,0,-1,1};
std::queue> Q;
Q.push(std::make_pair(x,y));
mark[x][y]=1;
while(!Q.empty()){
x=Q.front().first;
y=Q.front().second;
Q.pop();
for(int i=0;i<4;i++){
int newx=dx[i]+x;
int newy=dy[i]+y;
if(newx <0 || newx >=mark.size() || newy <0 || newy >=mark[0].size()){
continue;
}
if(mark[newx][newy]==0 && grid[newx][newy]=='1'){
mark[newx][newy]=1;
Q.push(make_pair(newx,newy));
}
}
}
}
};
只要判断循环就用快慢指针思想!!
class Solution {
public:
bool isHappy(int n) {
if(n==1){
return true;
}
int fast=_change(n);
int slow=fast;
do{
fast=_change(fast);
fast=_change(fast);
slow=_change(slow);
if(fast==1){
return true;
}
}while(fast!=slow);
return false;
}
int _change(int n){
int result=0;
while(n!=0){
result+=(n%10)*(n%10);
n=n/10;
}
return result;
}
};
虽然简单,但这种从低位向上穷举的思想还是挺不错的!
class Solution {
public:
int countPrimes(int n) {
vector prim(n,true);
for(int i=2;i
经典必会题,不解释!!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* result=NULL;
while(head)
{
ListNode* temp=head->next;
head->next=result;
result=head;
head=temp;
}
return result;
}
};
拓扑排序!!!
class Solution {
public:
struct GraphNode
{
int val;
vector neighbers;
GraphNode(int x):val(x){};
};
bool canFinish(int numCourses, vector>& prerequisites) {
vector graph;
//入度数组
vector degree;
for(int i=0;ineighbers.push_back(to);
degree[to->val]++;
}
std::queue q;
for(int i=0;ineighbers.size();i++){
degree[node->neighbers[i]->val]--;
if(degree[node->neighbers[i]->val]==0 ){
q.push(node->neighbers[i]);
}
}
}
for(int i=0;i
class Trie {
public:
/** Initialize your data structure here. */
Trie() {
is_end=false;
memset(next,0,sizeof(next));
}
/** Inserts a word into the trie. */
void insert(string word) {
Trie *node=this;
for(char c : word){
if(node->next[c-'a']==NULL){
node->next[c-'a']=new Trie();
}
node = node->next[c-'a'];
}
node->is_end=true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
Trie *node=this;
for(auto c : word){
node=node->next[c-'a'];
if(node==NULL){
return false;
}
}
return node->is_end;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
Trie *node = this;
for(char c: prefix){
node=node->next[c-'a'];
if(node==NULL){
return false;
}
}
return true;
}
private:
Trie* next[26];
bool is_end;
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
又是拓扑排序!!!
class Solution {
private:
struct GraphNode{
int val;
vector neighbers;
GraphNode(int x):val(x){}
};
public:
vector findOrder(int numCourses, vector>& prerequisites) {
vector graph;
vector degree(numCourses,0);
//初始化图
for(int i=0;ival]++;
from->neighbers.push_back(to);
}
//初始化队列
vector result;
queue q;
for(int i=0;ineighbers.size();i++){
degree[node->neighbers[i]->val]--;
if(degree[node->neighbers[i]->val]==0){
result.push_back(node->neighbers[i]->val);
q.push(node->neighbers[i]);
}
}
}
for(int i=0;i
遇到第K大这种问题记得考虑优先级队列!!!!
class Solution {
public:
int findKthLargest(vector& nums, int k) {
std::priority_queue,std::greater > small_heap;
for(int i=0;ismall_heap.top()){
small_heap.pop();
small_heap.push(nums[i]);
}
}
}
return small_heap.top();
}
};
一行代码解决!!
class Solution {
public:
bool containsDuplicate(vector& nums) {
return nums.size() > unordered_set(nums.begin(), nums.end()).size();
//如果原数组的大小>集合的大小,则说明存在重复元素
}
};