45.圆圈中最后剩下的数字 知识点:链表的遍历 注意for循环中m-1,才是找到要删除的点 创新解法还不会
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if (n <1|| m<1)
return -1;
list<int> numbers;
for(int i = 0; i<n; i++)
numbers.push_back(i);
list<int>::iterator current;
list<int>::iterator del;
current = numbers.begin();
while(numbers.size() > 1)
{
for(int i = 0;i<m-1;i++)
{
current++;
if (current == numbers.end())
current = numbers.begin();
}
del = current++;
if (current == numbers.end())
current = numbers.begin();
numbers.erase(del);
}
return *current;
}
};
链表中环的入口结点
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if (pHead->next == NULL)
return NULL;
ListNode* slow;
ListNode* fast;
slow = pHead;
fast = pHead;
int count = 0;
do
{
slow = slow->next;
fast = fast->next->next;
count++;
}while(slow != fast);
fast = pHead;
while(fast!=slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
二叉树的下一个结点 知识点;二叉树的遍历高级变种 最开始没有加father!=NULL判断,导致一直通不过,指定结点完全有可能是最后一个结点
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if (pNode->right != NULL)
{
pNode = pNode->right;
while(pNode->left!=NULL)
{
pNode = pNode->left;
}
return pNode;
}
else
{
TreeLinkNode* father = pNode->next;
while(father->left != pNode && father != NULL)
{
pNode = father ;
father = pNode->next;
}
return father;
}
}
};
数字在排序数组中出现的次数 知识点:二分查找 题目中说了排序数组,没有的话就用hash方法吧。
class Solution {
public:
int GetNumberOfK(vector<int> data, int k) {
int length = data.size();
int l = 0;
int r = length - 1;
int minus = -1;
if (data[r]> data[l])
minus = 1;
while (l <= r)
{
int mid = l + (r-l)/2;
if (data[mid] == k)
{
int first = mid ;
int last = mid ;
while (first >= 0 && data[first] == data[mid])
{
first--;
}
while (last < length &&data[last] == data[mid])
{
last++;
}
return last - first - 1;
}
else if (data[mid] <k)
{
if (minus == 1)
l = mid + 1;
else
r = mid;
}
else
{
if (minus == 1)
r = mid;
else
l = mid + 1;
}
}
return 0;
}
};
二分查找要注意三个问题,一是数据量要大于1; 二是数据中到底有没有这个数,这关系到能不能跳出循环;有个死角是数组的最后一个数是没法判断到的。 。上面的代码就有这三个问题,下面两种方法是正确的
class Solution {
public:
int GetNumberOfK(vector<int> data, int k) {
if (data.size()<2)
{
if (data.empty())
return 0;
if (data[0]==k)
return 1;
else
return 0;
}
int length = data.size();
int l = 0;
int r = length - 1;
int minus = -1;
if (data[r]> data[l])
minus = 1;
while (l <= r)
{
int mid = l + (r-l)/2;
if (data[mid] == k )
{
int first = mid ;
int last = mid ;
while (first >= 0 && data[first] == data[mid])
{
first--;
}
while (last < length &&data[last] == data[mid])
{
last++;
}
return last - first - 1;
}
else if (data[mid] <k)
{
if (minus == 1)
l = mid + 1 ;
else
r = mid-1 ;
}
else
{
if (minus == 1)
r = mid -1;
else
l = mid + 1;
}
}
return 0;
}
};
class Solution {
public:
int GetNumberOfK(vector<int> data, int k) {
if (data.size()<2)
{
if (data.empty())
return 0;
}
int length = data.size();
int l = 0;
int r = length - 1;
int minus = -1;
if (data[r]> data[l])
minus = 1;
while (l < r)
{
int mid = l + (r-l)/2;
if (data[mid] == k )
{
int first = mid ;
int last = mid ;
while (first >= 0 && data[first] == data[mid])
{
first--;
}
while (last < length &&data[last] == data[mid])
{
last++;
}
return last - first - 1;
}
else if (data[mid] <k)
{
if (minus == 1)
l = mid + 1 ;
else
r = mid -1 ; //r = mid也行
}
else
{
if (minus == 1)
r = mid -1 ; //r = mid 也行
else
l = mid + 1;
}
}
if (data[l] == k)
return 1;
return 0;
}
};
主要是三个两个地方,一个是while要不要等于号,另一个是r = mid还是r=mid -1 如果要等于号,必须r =mid -1,否则有可能跳不出循环,r= mid -1必须数据的个数最少1个。 如果不要等于号,r = mid,r = mid -1可以只是一个数,但是会剩一个数没有判断,就是l==r的那个位置的,要拿出来单独判断。
42.左旋转字符串 找到规律了就不难了
class Solution {
public:
string LeftRotateString(string str, int n) {
int length = str.size();
revise(str, 0, length-1);
revise(str,0, length-n-1);
revise(str, length-n, length-1);
return str;
}
void revise(string&str,int begin, int end)
{
int l = begin;
int r = end;
while(l<r)
{
char temp = str[r];
str[r] = str[l];
str[l] = temp;
l++;
r--;
}
}
};
22.栈的压入弹出队列 思路很简单, 如果stackData要不然压入一个新的数,要不然弹出一个数
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
bool bPossible = false;
if (pushV.empty() || popV.empty())
return bPossible;
std::stack<int> stackData;
int i = 0;
int j = 0;
for(; i<pushV.size(), j<popV.size(); )
{
if (stackData.empty() ||stackData.top() != popV[j])
{
stackData.push(pushV[i]);
i++;
}
if (stackData.top() == popV[j])
{
stackData.pop();
j++;
}
}
if (stackData.empty())
bPossible = true;
return bPossible;
}
};
和为S的连续正数序列 知识点:尺取法
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
int begin = 1;
int end = 2;
int total = begin + end;
vector<vector<int> > result;
while(begin<sum)
{
if (total == sum)
{
saveData(result, begin, end);
total -=begin++;
}
else if (total<sum)
{
total += ++end;
}
else
{
total -= begin++;
}
}
return result;
}
void saveData(vector<vector<int> > &result, int begin, int end)
{
vector<int> temp;
while(begin<=end)
{
temp.push_back(begin);
begin++;
}
result.push_back(temp);
}
};
二叉搜索树与双向链表 知识点:遍历 其实可以看做是求最大值的升级版visit函数修改全局变量, 因为要从小到大,所以选择中序遍历
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if (pRootOfTree == NULL)
return NULL;
TreeNode* pLastNodeInList = NULL;
ConvertNode(pRootOfTree, &pLastNodeInList);
TreeNode* pHeadOfList = pLastNodeInList;
while(pHeadOfList != NULL && pHeadOfList->left!=NULL)
pHeadOfList = pHeadOfList->left;
// while( pLastNodeInList->left != NULL )
// pLastNodeInList = pLastNodeInList->left;
return pHeadOfList;
}
void ConvertNode(TreeNode*pNode , TreeNode** pLastNodeInList)
{
if (pNode)
{
ConvertNode(pNode->left , pLastNodeInList);
TreeNode* current = pNode;
current->left = *pLastNodeInList;
if (*pLastNodeInList != NULL)
(*pLastNodeInList)->right = current;
*pLastNodeInList = current;
ConvertNode(pNode->right, pLastNodeInList);
}
}
};
从上往下打印二叉树 知识点;二叉树遍历, 迭代法
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> result;
if (root==NULL)
return result;
std::deque<TreeNode*> dequeTreeNode;
dequeTreeNode.push_back(root);
while(!dequeTreeNode.empty())
{
TreeNode* pNode = dequeTreeNode.front();
dequeTreeNode.pop_front();
result.push_back(pNode->val);
if (pNode->left != NULL)
dequeTreeNode.push_back(pNode->left);
if (pNode->right != NULL)
dequeTreeNode.push_back(pNode->right);
}
return result;
}
};
数组中只出现一次的数字 知识点:是一个的升级版,三个的话那就没辙了, 三个数不相同不能保证异或结二进制中有两个1.如11,10,01;
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int num = 0;
for(int i = 0; i<data.size();i++)
num ^= data[i];
int onebit = num&(num -1);
onebit = num^onebit;
int num11 = 0;
int num22 = 0;
for(int i = 0; i<data.size();i++)
{
if (data[i]&onebit)
num11 ^=data[i];
else
num22 ^= data[i];
}
*num1 = num11;
*num2 = num22;
}
};