字符流中第一个不重复的字符 疑惑点在如何确定第一个的,下面的空间复杂度有点高
class Solution
{
public:
//Insert one char from stringstream
void Insert(char ch)
{
str += ch;
count[ch]++;
}
//return the first appearence once char in current stringstream
char FirstAppearingOnce()
{
int len = str.size();
for (int i = 0; i<len;i++){
if (count[str[i]] == 1)
return str[i];
}
return '#';
}
string str;
int count[256] = {0};
};
数据流中的中位数 用一个大顶堆和小顶堆来实现
class Solution {
public:
priority_queue<int, vector<int>, less<int> > p;
priority_queue<int, vector<int>, greater<int> > q;
void Insert(int num)
{
if(p.empty() || num <= p.top()) p.push(num);
else q.push(num);
if(p.size() == q.size() + 2) q.push(p.top()), p.pop();
if(p.size() + 1 == q.size()) p.push(q.top()), q.pop();
}
double GetMedian()
{
return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
}
};
用sort也可以实现的
class Solution {
public:
vector<int> data;
void Insert(int num)
{
data.push_back(num);
}
double GetMedian()
{
sort(data.begin(), data.end());
int mid = data.size()/2;
if (data.size()&1)
{
return data[mid];
}
else
return (data[mid]+data[mid-1])*0.5;
}
};
二叉树中和为某一值的路径 就是先序遍历
class Solution {
vector<vector<int> >allRes;
vector<int> tmp;
void dfsFind(TreeNode * node , int left){
tmp.push_back(node->val);
if(left-node->val == 0 && !node->left && !node->right)
allRes.push_back(tmp);
else {
if(node->left) dfsFind(node->left, left-node->val);
if(node->right) dfsFind(node->right, left-node->val);
}
tmp.pop_back();
}
public:
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
if(root) dfsFind(root, expectNumber);
return allRes;
}
};
数组中出现次数超过一半的数字
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if (numbers.size() == 0)
return -1;
int member = numbers[0];
int count = 1;
for(int i= 1; i<numbers.size();i++)
{
if (numbers[i] == member)
{
count++;
}
else
{
if (count==0)
{
member = numbers[i];
count = 1;
}
count--;
}
}
if (count>0)
return member;
else
return 0;
}
};
合并两个排序的链表
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if (pHead1==NULL)
return pHead2;
if (pHead2==NULL)
return pHead1;
ListNode* pHead = NULL;
{
if (pHead1->val < pHead2->val)
{
pHead = pHead1;
pHead->next = Merge( pHead1->next, pHead2);
}
else
{
pHead = pHead2;
pHead->next = Merge( pHead1, pHead2->next);
}
}
return pHead;
}
};
最小的k个数
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
multiset<int, greater<int> >kmin;
vector<int> result;
for (int i = 0; i<input.size();i++)
{
if (kmin.size() < k)
{
kmin.insert(input[i]);
}
else
{
multiset<int, less<int> >::iterator iter = kmin.begin();
if (*iter > input[i])
{
kmin.erase(iter);
kmin.insert(input[i]);
}
}
}
if (kmin.size() == k)
result.assign(kmin.begin(), kmin.end());
return result;
}
};
两个链表的第一个公共节点
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* headA, ListNode* headB) {
if (headA== NULL || headB == NULL)
return NULL;
ListNode* p1 = headA;
ListNode* n1 = headA;
ListNode* n2 = headB;
ListNode* p2 = headB;
//找出两个链表的长度差;
while(p1!=NULL || p2!= NULL)
{
if( p1==NULL)
{
n2 = n2->next;
}
else if( p2==NULL)
{
n1 = n1->next;
}
p1 = p1==NULL?p1:p1->next;
p2 = p2==NULL?p2: p2->next;
}
while (n1!=n2 )
{
n1 = n1->next;
n2 = n2->next;
}
return n1;
}
};
很奇怪,下面这种方法在牛客网通不过(复杂度太大), 在leetcode到是能通过
class Solution {
public:
ListNode *getIntersectionNode(ListNode *pHead1, ListNode *pHead2) {
ListNode* first = pHead1;
ListNode* second = pHead2;
int size1 = 0;
int size2 = 0;
while(first!=NULL)
{
size1++;
first = first->next;
}
cout<<size1;
first = pHead1;
while(second!=NULL)
{
size2++;
second = second->next;
}
cout<<size2;
second = pHead2;
if (size1>size2)
{
int n = size1 - size2;
while(n--)
{
first = first->next;
}
}
else{
int n = size2 - size1;
while(n--)
{
second = second->next;
}
}
while(first != NULL){
if(first == second) return first;
first = first->next;
second = second->next;
}
return NULL;
}
};
重建二叉树 这道题没啥难度,倒是在 TreeNode* root = new TreeNode();卡了下,会编译不通过
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if (pre.size() == 0 || vin.size() == 0 || pre.size() != vin.size())
return NULL;
return ConstructCore(pre, 0, pre.size()-1, vin, 0, vin.size()-1);
}
TreeNode* ConstructCore(vector<int>& pre, int begin, int end, vector<int>&vin, int first, int second)
{
TreeNode* root = new TreeNode(pre[begin]);
if (first==second)
return root;
int mid ;
for (mid = first; mid<=second && vin[mid]!= pre[begin];mid++);
if (mid>first)
root->left = ConstructCore(pre, begin+1, begin + mid-first, vin, first, mid-1);
if (mid <second)
root ->right = ConstructCore(pre, end - (second-mid) + 1, end, vin, mid+1, second);
return root;
}
};
数值的整数次方 知识点:主要是特殊情况的考虑
class Solution {
public:
double Power(double base, int exponent) {
bool InvalidInput = false;
if (exponent < 0 && base <exp(-10) && base> -exp(10) )
{
InvalidInput = true;
return 0.0;
}
unsigned int exp = exponent;
if (exponent< 0)
exp = -exponent;
double result = 1.0;
for (int i = 0; i<exp;i++)
result *=base;
if (exponent < 0)
return 1/result;
return result;
}
};
调整数组顺序使奇数位于偶数面前 知识点:使用两个指针
class Solution {
public:
void reOrderArray(vector<int> &array) {
int bindex = 0;
int eindex = 0;
for (int i= 0; i<array.size();i++)
{
if (array[i]%2)
{
moveonestep(array, bindex, eindex);
bindex++;
}
eindex++;
}
}
void moveonestep(vector<int>& array, int begin,int end)
{
int temp = array[end];
for (int i = end;i > begin;i--)
{
array[i] = array[i-1];
}
array[begin] = temp;
}
};
扑克牌顺子 知识点:
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
if (numbers.size() < 5)
return false;
sort(numbers.begin(), numbers.end());
int banking = 0;
int zeroNum = 0;
for (int i = 0; i<numbers.size()-1;i++)
{
if (numbers[i] == 0)
zeroNum ++;
else if (numbers[i+1] == numbers[i])
return false;
else if (numbers[i+1] > numbers[i])
{
banking += numbers[i+1] - numbers[i] -1;
}
}
if (zeroNum>= banking)
return true;
else
return false;
}
};
矩阵中的路径
顺时针打印矩阵路径
class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
int rows = matrix.size();
vector<int> member = matrix[0];
int columns = member.size();
vector<int> result;
if (rows == 0 || columns == 0)
return result;
int start = 0;
while (columns > start*2 && rows > start*2)
{
PrintMatrixCircle(matrix, result, columns, rows, start);
start++;
}
return result;
}
void PrintMatrixCircle(vector<vector<int> > & matrix, vector<int>& result,int columns, int rows, int start)
{
int endx = columns - 1 - start;
int endy = rows -1 - start;
for (int i= start;i<=endx; i++)
{
vector<int> member = matrix[start];
result.push_back(member[i]);
}
for (int j = start+1; j<= endy; j++ )
{
vector<int> member = matrix[j];
result.push_back(member[endx]);
}
for (int i = endx-1;endy>start&& i>= start;i--)
{
vector<int> member = matrix[endy]; //第一次这里搞错了 endx
result.push_back(member[i]);
}
for (int j = endy-1;start< endx &&j>= start+1; j--)
{
vector<int> member = matrix[j];
result.push_back(member[start]);
}
}
};
丑数
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index< 1)
return 0;
const int num = index;
vector<int> result(num);
result[0] = 1;
int index2 = 0;
int index3 = 0;
int index5 = 0;
for (int i= 1; i<num;i++)
{
int data = min(result[index2]*2, result[index3]*3, result[index5]*5);
result[i] = data;
if (result[index2]*2<=data)
index2++;
if (result[index3]*3 <=data)
index3++;
if (result[index5]*5 <= data)
index5++;
}
return result.back();
}
int min(int a, int b, int c)
{
int temp = a<b?a:b;
int mini = temp<c?temp:c;
return mini;
}
};
第一次只出现一次的字符
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int count[256] = {0};
int length = str.size();
for(int i= 0; i<length;i++)
{
count[str[i]]++;
}
for (int i = 0; i<length; i++)
{
if (count[str[i]] == 1)
return i;
}
return -1;
}
};
包含min函数的栈
class Solution {
public:
void push(int value) {
elements.push(value);
if ( minStack.size() == 0 || value<minStack.top())
minStack.push(value);
else
minStack.push(minStack.top());
}
void pop() {
minStack.pop();
elements.pop();
}
int top() {
return elements.top();
}
int min() {
return minStack.top();
}
stack<int> minStack;
stack<int> elements;
};
二叉搜索树的后序遍历序列
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
int length = sequence.size();
if (length == 0)
return false;
if (length == 1)
return true;
return aftervisit(sequence, 0, length -1);
}
bool aftervisit(vector<int>& sequence, int begin, int end )
{
if (begin==end)
return true;
int root = sequence[end];
int k = begin;
for (; k<end;k++)
{
if (sequence[k]> root)
break;
}
int rbegin = k;
for(;rbegin<end;rbegin++)
{
if (sequence[rbegin]< root)
{
return false;
}
}
bool left = true;
bool right = true;
if (k -1>begin) left = aftervisit(sequence, begin, k-1 );
if ( k < end) right = aftervisit(sequence, k,
end-1 ); //这里卡了挺久的,最开始是end
return(left&&right);
}
};
删除链表中重复的节点
这种做法比较好,自己先建立一个头结点,避免了删除头结点带来额外的复杂度
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
ListNode* pNew = new ListNode(0);
ListNode* pTmp = pNew;
ListNode* pCur = pHead;
ListNode* pDel = NULL;
while(pCur){
if(pCur->next!=NULL && pCur->val==pCur->next->val){
pDel=pCur;
ListNode* pNext=pCur->next;
delete pDel;
while(pNext->next!=NULL && pNext->val==pNext->next->val){
pDel=pNext;
pNext=pNext->next;
delete pDel;
}
pDel=pNext;
pCur=pNext->next;
delete pDel;
}
else{
pTmp->next=pCur;
pTmp=pTmp->next;
pCur=pCur->next;
}
}
pTmp->next=NULL;
return pNew->next;
}
};
序列化二叉树 没怎么懂反序列化的
typedef TreeNode node;
typedef TreeNode* pnode;
typedef int* pint;
class Solution {
vector<int> buf;
void dfs(pnode p){
if(!p) buf.push_back(0x23333);
else{
buf.push_back(p -> val);
dfs(p -> left);
dfs(p -> right);
}
}
pnode dfs2(pint& p){
if(*p == 0x23333){
++p;
return NULL;
}
pnode res = new node(*p);
++p;
res -> left = dfs2(p);
res -> right = dfs2(p);
return res;
}
public:
char* Serialize(TreeNode *p) {
buf.clear();
dfs(p);
int *res = new int[buf.size()];
for(unsigned int i = 0; i < buf.size(); ++i) res[i] = buf[i];
return (char*)res;
}
TreeNode* Deserialize(char *str) {
int *p = (int*)str;
return dfs2(p);
}
};
复杂链表的复制
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
CloneNodes(pHead);
ConnectSliblingNodes(pHead);
return ReconnectNodes(pHead);
}
void CloneNodes(RandomListNode* pHead)
{
RandomListNode* pNode = pHead;
while (pNode)
{
RandomListNode* pCloned = new RandomListNode(pNode->label);
pCloned->next = pNode->next;
pCloned->random = NULL;
pNode->next = pCloned;
pNode = pCloned->next;
}
}
void ConnectSliblingNodes(RandomListNode* pHead)
{
RandomListNode* pNode = pHead;
while(pNode)
{
RandomListNode* pCloned = pNode->next;
if (pNode->random != NULL)
pCloned->random = pNode->random->next;
pNode = pCloned->next;
}
}
RandomListNode* ReconnectNodes(RandomListNode* pHead)
{
RandomListNode* pNode = pHead;
RandomListNode* pClonedHead = NULL;
// RandomListNode* pNode = NULL;
if (pHead != NULL)
{
pClonedHead = pHead->next;
}
while(pNode != NULL)
{
RandomListNode* pClonedNode = pNode->next;
RandomListNode* pNextNode = pNode->next->next;
pNode->next = pClonedNode->next;
if (pNextNode!=NULL)
{
pClonedNode->next = pNextNode->next;
}
else
{
pClonedNode->next = NULL;
}
pNode = pNextNode;
}
return pClonedHead;
}
};
字符串的排列 在这道题做了好久,一直卡在如何去重的问题上,自己跟自己交换重复如何解决。本想在遍历的时候能够去重,但是发现问题很大,最后不得不搬出STL了。
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> result;
if (str.size() < 1)
return result;
if (str.size() == 1)
result.push_back(str);
// result.push_back(str);
else if (str.size() > 1){
function(str, 0, str.size()-1, result);
}
sort(result.begin(),result.end());
auto it = unique(result.begin(),result.end());
result.erase(it,result.end());
return result;
}
void function(string& str, int begin, int end, vector<string>& result)
{
result.push_back(str);
for(int i = begin ; i<= end; i++)
{
swap(str[i], str[begin]);
function(str, begin+1 , end, result);
swap(str[i], str[begin]);
}
}
};
把字符串转换成整数 没有判断溢出也通过了,我只判断了正负号和是否无效字符
class Solution {
public:
int StrToInt(string str) {
bool invalid = true;
bool isMinus = false;
bool overflow = false;
int index = 0;
if (str[0] == '-'|| str[0] == '+' )
index = 1;
if (str[0] == '-')
isMinus = true;
if (str[0] == '+')
isMinus = false;
long long int sum = 0;
for (;index<str.size();index++)
{
if (str[index]<'0' || str[index] > '9')
{
invalid = true;
return 0;
}
int num = str[index] - '0';
sum = sum*10 + num;
}
if (isMinus)
return sum*(-1);
return sum;
}
};
滑动窗口的最大值 仔细想一下,也不难,保存一个size大小的队列就够了,但是队列可以优化一下
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> result;
int length = num.size();
if (length < size || size<=0)
return result;
std::deque<int> queue;
for (int i = 0; i<size; i++)
{
while (!queue.empty() && num[i] >= num[queue.back()])
queue.pop_back();
queue.push_back(i);
}
// if (queue.empty())
// return result;
result.push_back(num[queue.front()]);
for(int i = size;i<length; i++)
{
while (!queue.empty() && i - queue.front()>size - 1)
{
queue.pop_front();
}
while (!queue.empty() && num[i] > num[queue.back()])
{
queue.pop_back();
}
queue.push_back(i);
result.push_back(num[queue.front()]);
}
return result;
}
};
正则表达式匹配 这题比较复杂得仔细看看
/*
思路:只有当模式串和字符串同时等于\0,才可以认为两个串匹配。
在匹配中,对于每个位的匹配可以分为三种情况
1、(相应位匹配||模式串为.&&字符串不是\0)&&模式串下一位是*
2、(相应位匹配||模式串为.&&字符串不是\0)&&模式串下一位不是*
3、相应位不匹配&&(模式位不为.||字符串是\0)
对应1,最复杂。分为*取0,*取1,*>=2三种情况。
*取0对应跳过当前匹配位,继续寻找patter的下一个匹配位,str不变,pattern+2
*取1对应当前匹配位算一次成功匹配,str+1,pattern+2
*取>=2对应一次成功匹配,继续匹配字符串的下一位是否匹配,str+1,pattern不变
三者取或。即只要有一种情况能匹配成功认为字符串就是匹配成功的。
对应2,相当于一次成功匹配,str+1,pattern+1
对应3,匹配失败,直接返回false
*/
class Solution {
public:
bool match(char* str, char* pattern)
{
if(str==NULL||pattern==NULL)
return false;
return matchCore(str,pattern);
}
bool matchCore(char* str, char* pattern)
{
if(*str=='\0'&&*pattern=='\0')
return true;
if(*str!='\0'&&*pattern=='\0')
return false;
if(*(pattern+1)=='*')
{
if(*pattern==*str||(*pattern=='.'&&*str!='\0'))
/*
matchCore(str,pattern+2):模式串未匹配
matchCore(str+1,pattern):模式串已经匹配成功,尝试匹配下一个字符串
matchCore(str+1,pat+2):模式串已经成功匹配,并且不匹配下一个字符串内容 注意这里 matchCore(str+1,pat+2)重复考虑了(代码中已经去除),谢谢@chlq的指出 */
return matchCore(str+1,pattern)||matchCore(str,pattern+2);
else
return matchCore(str,pattern+2);
}
if(*str==*pattern||(*pattern=='.'&&*str!='\0'))
return matchCore(str+1,pattern+1);
return false;
}
};
表示数值的字符串
class Solution {
public:
bool isNumeric(char* string)
{
if (string == NULL)
return false;
if (*string == '+'|| *string == '-')
string++;
if (*string =='\0')
return false;
bool numeric = true;
scanDigits(&string);
if (*string !='\0'){
if(*string == '.')
{
++string;
scanDigits(&string);
if (*string == 'e' || *string =='E' )
numeric = isExponential(&string);
}
else if (*string == 'e' || *string =='E' )
{
numeric = isExponential(&string);
}
else numeric = false;
}
return numeric&&*string=='\0';
}
void scanDigits(char** string)
{
while(**string !='\0'&& **string>='0' && **string<= '9')
(*string)++;
}
bool isExponential(char** string)
{
++(*string);
if (**string == '+'|| **string == '-')
(*string)++;
if (**string =='\0')
return false;
scanDigits(string);
return (**string=='\0')?true:false;
}
};
数组中的逆序对 牛客网比书上数据量要大,另外一个排序的时候可以再优化一下,达到遍历一边就可以的效果
class Solution {
public:
int InversePairs(vector<int> data) {
if (data.empty())
return 0;
int length = data.size();
vector<int>copy(data.begin(), data.end());
int count = InversePairsCore(data, copy, 0, length - 1);
return count;
}
int InversePairsCore(vector<int>&data, vector<int>& copy, int start, int end)
{
if (start == end)
{
copy[start] = data[start];
return 0;
}
int mid = start + (end - start) / 2;
int left = InversePairsCore(data, copy, start, mid);
int right = InversePairsCore(data, copy, mid + 1, end);
int count = 0;
int p1 = mid, p2 = end;
while (p1 >= start && p2 >= mid + 1)
{
if (data[p1] > data[p2])
{
count += p2 - mid;
count = count%1000000007;
p1--;
}
else
{
p2--;
}
}
int i = start, j = mid + 1;
int m = mid, n = end;
int k = start;
while (i <= m && j <= n)
{
if (data[i] <= data[j])
copy[k++] = data[i++];
else if (data[i]> data[j])
copy[k++] = data[j++];
}
while (i <= m)
copy[k++] = data[i++];
while (j <= n)
copy[k++] = data[j++];
for (int i = start; i <= end; i++)
{
data[i] = copy[i];
// cout << data[i]<<ends;
}
return (left%1000000007 + right%1000000007 + count%1000000007)%1000000007;
}
};
矩阵中的路径 典型的dfs啦
class Solution {
public:
bool hasPath(char* matrix, int rows, int cols, char* str)
{
if (matrix==NULL || rows < 1 || cols < 1 || str == NULL)
return false;
bool *visited = new bool[rows*cols];
memset(visited, 0, rows*cols);
int pathLength = 0;
for (int row = 0; row<rows; row++)
{
for (int col = 0; col<cols;col++)
{
if (hasPathCore(matrix, rows, cols, row, col, str, pathLength, visited))
return true;
}
}
delete[] visited;
return false;
}
bool hasPathCore(char* matrix, int rows, int cols,int row, int col, char* str, int& pathLength, bool* visited)
{
if (str[pathLength] == '\0')
return true;
bool hasPath = false;
if (matrix[row*cols + col]== str[pathLength]&& visited[row*cols + col] == false && row>=0 &&row< rows && col>=0 && col<cols)
{
visited[row*cols + col] = true;
++pathLength;
hasPath = hasPathCore(matrix, rows, cols, row-1, col, str, pathLength, visited)
||hasPathCore(matrix, rows, cols, row+1, col, str, pathLength, visited)
||hasPathCore(matrix, rows, cols, row, col+1, str, pathLength, visited)
||hasPathCore(matrix, rows, cols, row, col-1, str, pathLength, visited);
if (!hasPath)
{
--pathLength;
visited[row*cols + col] = false;
}
}
return hasPath;
}
};
整数中1出现的次数 一种很简洁的解法,大神真是太多
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n){
int ones = 0;
for (long long m = 1; m <= n; m *= 10)
ones += (n/m + 8) / 10 * m + (n/m % 10 == 1) * (n%m + 1);
return ones;
}
};