1.数字在排序数组中出现的次数
使用二分法,可以将时间复杂度变成O(logn)
代码
#include <iostream>
using namespace std;
int getFirstK(int *arr, int len, int k, int s, int e)
{
if (arr == NULL || len <= 0 || s > e || s < 0 || e < 0)//参数检验
{
return -1;
}
int start = s;//0
int end = e;//7
int mid = (end - start) / 2 + start;
if (arr[mid] < k)//说明k在后半段
{
s = start + mid + 1;
return getFirstK(arr, len - mid - 1, k, s, e);
}
else if (arr[mid]>k || (arr[mid] == k && arr[mid - 1] == k))
{//说明k在前半段
e = len - mid - 2;
return getFirstK(arr, len - mid - 1, k, s, e);
}
else
{
return mid;
}
}
int getLastK(int *arr, int len, int k, int s, int e)
{
if (arr == NULL || len <= 0 || s > e || s < 0 || e < 0)
{
return -1;
}
int start = s;//0
int end = e;//7
int mid = (end - start) / 2 + start;
if (arr[mid] < k || (arr[mid] == k && arr[mid + 1] == k))//说明k在后半段
{
s = start + mid + 1;
return getLastK(arr, len - mid - 1, k, s, e);
}
else if (arr[mid]>k )
{//说明k在前半段
e = len - mid - 2;
return getLastK(arr, len - mid - 1, k, s, e);
}
else
{
return mid;
}
}
int getNumTime(int *a, int len,int k)
{
int start = getFirstK(a, len, k, 0, len - 1);
int end = getLastK(a, len, k, 0, len - 1);
if (start < 0 || end < 0)//表示没有这样的数字
{
return -1;
}
return end - start + 1;//坐标计算应当加一个1
}
int main()
{
//int a[8] = { 1,2,3,3,3,3,4,5 };
//int a[8] = { 1,2,3,4,5 };
int a[8] = { 1,2,4,4,5 };
cout << getFirstK(a, 5, 3, 0, 4) << endl;
cout << getLastK(a, 5, 3, 0, 4) << endl;
cout << getNumTime(a, 5, 3) << endl;
return 0;
}
2.二叉树深度和拓展
二叉树深度:
int getDepth(treeNode* s)
{
if (s == NULL)
{
return 0;
}
else
{
int tmp1 = getDepth(s->left);
int tmp2 = getDepth(s->right);
return (tmp1> tmp2 ? tmp1 : tmp2) + 1;
}
}
判断是否是平衡二叉树:
bool isBalance(treeNode* s)
{
if (s == NULL)
{
return true;
}
int left = getDepth(s->left);
int right = getDepth(s->right);
if (abs(left - right) > 1)
{
return false;
}
return isBalance(s->left) && isBalance(s->right);
}
优化判断:
bool isBetterBalance(treeNode* pRoot,int* pDepth)//减少了重复对结点访问的操作
{
if (pRoot == NULL)
{
*pDepth = 0;
return true;
}
int left, right;
if (isBetterBalance(pRoot->left, &left) &&
isBetterBalance(pRoot->right, &right))
{
int diff = left - right;
if (diff <= 1 && diff >= -1)
{
*pDepth = 1+(left > right ? left : right);
return true;
}
}
return false;
}
bool isBetterBalanced(treeNode* pRoot)
{
int depth = 0;
return isBetterBalance(pRoot, &depth);
}
3.数组中只出现一次的数字
一个整形数组里除了两个数字之外其他数字都出现了两次
unsigned int FindFirstBitIs1(int num)
{
int indexBit = 0;
while ((num & 1) == 0 && (indexBit < 8 * sizeof(int)))
{
num = num >> 1;
++indexBit;
}
return indexBit;
}
bool IsBit1(int num, unsigned int indexBit)
{
num = num >> indexBit;
return (num & 1);
}
void FindNumsAppearOnce(int data[], int length, int* num1, int* num2)
{
if (data == NULL || length < 2)
return;
int resultExclusiveOR = 0;
for (int i = 0; i < length; ++i)
{
resultExclusiveOR ^= data[i];
}
unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
*num1 = *num2 = 0;
for (int j = 0; j < length; ++j)
{
if (IsBit1(data[j], indexOf1))//为1的在一起相抑或
{
*num1 ^= data[j];
}
else
{
*num2 ^= data[j];
}
}
}
int main()
{
int arr[8] = { 2,4,3,6,3,2,5,5 };
int tmp1;
int tmp2;
FindNumsAppearOnce(arr, 8, &tmp1, &tmp2);
cout << tmp1<<endl;
cout << tmp2<<endl;
return 0;
}
4.和为k的两个数字
数组是有序递增数组
bool findCoupleSumk(int* a, int len, int* tmp1, int* tmp2, int k)
{
if (a == NULL || len <= 1)
{
return false;
}
int *p1 = &a[0];
int *p2 = &a[len - 1];
while (*p1 + *p2 != k&&p1 != p2)
{
if (*p1 + *p2 < k)
{
p1++;
}
else
{
p2--;
}
}
if (p1 == p2)
{
return false;
}
*tmp1 = *p1;
*tmp2 = *p2;
return true;
}
拓展:连续数组
void findSum(int *arr, int len, int k)
{
if (arr == NULL || len <= 0 || k < 3)//要考虑参数k有无可能输入错误
{
cout << "无" << endl;
return;
}
if (len == 1 && arr[0] == k)
{
cout << arr[0] << endl;
return;
}
else if (len == 1 && arr[0] != k)
{
cout << "无" << endl;
return;
}
int first = 0;
int second = 1;
int sum = 0;
int flag = false;
while (second <= len - 1 && first <= second)
{
for (int i = first; i <= second; ++i)
{
sum += arr[i];
}
if (sum < k)
{
second++;
sum = 0;
}
else if (sum>k)
{
first++;
sum = 0;
}
else
{
flag = true;
for (int i = first; i <= second; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
sum = 0;
second++;
}
}
if (flag == false)
{
cout << "没有连续数的和是" << k << "的值\n";
}
}
int main()
{
int arr[8] = { 1,2,3,4,5,6,7,8 };
int* brr = NULL;
findSum(arr, 8, 15);
findSum(arr, 8, 1001);
findSum(brr, 0, 15);
return 0;
}
5.
反转单词顺序以及左旋转字符串
void reserve(char* p1,char* p2,int len)
{
if (p1 == p2)
{
return;
}
char tmp;
int time = 0;
while (p1 != p2&&time<len/2)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
time++;
}
}
void reserveWord(char* arr,int len)
{
if (arr == NULL||len<=1)
{
return;
}
reserve(&arr[0], &arr[len - 1], len);
cout << arr << endl;
char* p1 = &arr[0];
char* p2 = &arr[0];
int tmp = 0;
while (*p2 != '\0')
{
if (*p2 == ' ')
{
reserve(p1, p2-1, tmp);
p1 += tmp+1;
p2 = p1;
tmp = 0;
}
p2++;
tmp++;
}
}
//拓展:英文左旋转
char *LeftRotateString(char* pStr, int n)
{
if (pStr != NULL)
{
int nlength = static_cast<int>(strlen(pStr));
if (nlength > 0 && n > 0 && n < nlength)
{
char* pFirstStart = pStr;
char* pFirstEnd = pStr + n - 1;
char* pSecondStart = pStr + n;
char *pSecondEnd = pStr + nlength - 1;
reserve(pFirstStart, pFirstEnd, n );
reserve(pSecondStart, pSecondEnd, nlength - n);//7 2
reserve(pFirstStart, pSecondEnd, nlength - 1);
}
}
return pStr;
}
int main()
{
// char a[] = "I am a student.";
// reserveWord(a, strlen(a));
// cout << a << endl;
char arr[] = "abcdefg";
char* p = LeftRotateString(arr, 2);
cout << p << endl;
return 0;
}