11.数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
思路:首先处理指数为正数的情况,然后如果指数为负且底数不为0,结果取倒数。注意double类型相等的比较。
class Solution {
public:
bool g_InvalidInput = false;
double Power(double base, int exponent) {
g_InvalidInput = false;
if(equal(base,0.0) && exponent < 0){
g_InvalidInput = true;
return 0.0;
}
unsigned int absExponent = (unsigned int)(exponent);
if(exponent < 0)
absExponent = (unsigned int)(-exponent);
double result = PowerWithUnsignedExponent(base, absExponent);
if(exponent < 0)
result = 1.0 /result;
return result;
}
double PowerWithUnsignedExponent(double base,unsigned int exponent){
if(exponent == 0) return 1;
if(exponent == 1) return base;
double result = PowerWithUnsignedExponent(base, exponent >> 1);
result *= result;
if(exponent & 0x1 == 1)
result *= base;
return result;
}
bool equal(double num1, double num2){
if((num1 - num2 < 0.0000001) &&
(num1 - num2 > -0.0000001))
return true;
else
return false;
}
};
12.打印1到最大的n位数
思路:
void Print1ToMaxOfNDigits_1(int n)
{
if (n <= 0)
return;
char *number = new char[n + 1];
memset(number, '0', n);
number[n] = '\0';
while (!Increment(number))
{
PrintNumber(number);
}
delete[]number;
}
// 字符串number表示一个数字,在 number上增加1
// 如果做加法溢出,则返回true;否则为false
bool Increment(char* number)
{
bool isOverflow = false;
int nTakeOver = 0;
int nLength = strlen(number);
for (int i = nLength - 1; i >= 0; i--)
{
int nSum = number[i] - '0' + nTakeOver;
if (i == nLength - 1)
nSum++;
if (nSum >= 10)
{
if (i == 0)
isOverflow = true;
else
{
nSum -= 10;
nTakeOver = 1;
number[i] = '0' + nSum;
}
}
else
{
number[i] = '0' + nSum;
break;
}
}
return isOverflow;
}
void PrintNumber(char* number)
{
bool isBeginning0 = true;
int nLength = strlen(number);
for (int i = 0; i < nLength; ++i)
{
if (isBeginning0 && number[i] != '0')
isBeginning0 = false;
if (!isBeginning0)
{
printf("%c", number[i]);
}
}
printf("\t");
}
13.在O(1)时间删除链表结点
给定单向链表的头指针和一个结点指针
思路:根据时间复杂度要求,此题目的前提是要删除的结点的确在链表中。令删除结点的值等于其后一个结点,并且指向其后一个结点的next。
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
if(!pListHead || !pToBeDeleted)
return;
// 要删除的结点不是尾结点
if(pToBeDeleted->m_pNext != nullptr)
{
ListNode* pNext = pToBeDeleted->m_pNext;
pToBeDeleted->m_nValue = pNext->m_nValue;
pToBeDeleted->m_pNext = pNext->m_pNext;
delete pNext;
pNext = nullptr;
}
// 链表只有一个结点,删除头结点(也是尾结点)
else if(*pListHead == pToBeDeleted)
{
delete pToBeDeleted;
pToBeDeleted = nullptr;
*pListHead = nullptr;
}
// 链表中有多个结点,删除尾结点
else
{
ListNode* pNode = *pListHead;
while(pNode->m_pNext != pToBeDeleted)
{
pNode = pNode->m_pNext;
}
pNode->m_pNext = nullptr;
delete pToBeDeleted;
pToBeDeleted = nullptr;
}
}
14.调整数组顺序使奇数位于偶数的前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分。(拓展:并保证奇数和奇数,偶数和偶数之间的相对位置不变)
思路:双向指针,交换,解耦合。拓展:类似冒泡排序,为了保持相对位置,只能交换相邻的两个元素。
class Solution {
public:
void reOrderArray(vector<int> &array) {
Reorder(array, isEven);
}
private:
static bool isEven(int n){
return (n & 1) == 0;
}
void Reorder(vector<int> &array, bool (func)(int)){
if(array.empty()) return;
int left = 0, right = array.size() - 1;
while(left < right){
while(left < right && !func(array[left]))
left++;
while(left < right && func(array[right]))
right--;
if(left < right){
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
}
}
};
class Solution {
public:
void reOrderArray(vector<int> &array) {
for(int i = 0;i < array.size();i++){
for(int j = array.size()-1; j>i;j--){
if(array[j]%2==1&&array[j-1]%2==0)
swap(array[j],array[j-1]);
}
}
}
};
15.链表中倒数第k个结点
输入一个链表,输出该链表中倒数第k个结点。
思路:考虑k=0以及k大于结点数的情况。先后指针,先指针经过k个结点,此时后指针从头结点开始于其同步移动。当先指针走完剩下的n-k个结点,后指针走了n-k步,指向了倒数第k个结点。(正数的n-k+1个结点就是倒数第k个结点)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead == NULL || k == 0) return NULL;
ListNode *pAhead = pListHead;
ListNode *pBehind = NULL;
for(unsigned int i = 0; i < k - 1; i++){
if(pAhead -> next != NULL)
pAhead = pAhead -> next;
else return NULL;
}
pBehind = pListHead;
while(pAhead -> next != NULL){
pAhead = pAhead -> next;
pBehind = pBehind -> next;
}
return pBehind;
}
};
16.反转链表
思路:利用两个指针分别指向当前结点与前一个结点。一旦当前结点的下一个结点为NULL时,该结点就是新的头结点。当前结点指向前一个结点。前一个结点=当前结点,当前结点=下一个结点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode *pReversedHead = NULL;
ListNode *pNode = pHead;
ListNode *pPrev = NULL;
while(pNode != NULL){
ListNode *pNext = pNode -> next;
if(pNext == NULL)
pReversedHead = pNode;
pNode -> next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReversedHead;
}
};
17.合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路:比较两个链表的头结点,取小的作为合并链表的头结点,递归调用函数,传入参数时,较小结点指向下一个结点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL) return pHead2;
if(pHead2 == NULL) return pHead1;
ListNode* pMergedHead = NULL;
if(pHead1 -> val < pHead2 -> val){
pMergedHead = pHead1;
pMergedHead -> next = Merge(pHead1 -> next, pHead2);
}
else{
pMergedHead = pHead2;
pMergedHead -> next = Merge(pHead1, pHead2 -> next);
}
return pMergedHead;
}
};
18.树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:首先比较根节点是否相等,如果不等则递归调用函数,看树A的左右子树是否含有树B。如果相等,则调用新函数一一比较每个结点。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool result = false;
if(pRoot1 != NULL && pRoot2 != NULL)
{
if(pRoot1->val == pRoot2->val)
result = DoesTree1HaveTree2(pRoot1, pRoot2);
if(!result)
result = HasSubtree(pRoot1->left, pRoot2);
if(!result)
result = HasSubtree(pRoot1->right, pRoot2);
}
return result;
}
private:
bool DoesTree1HaveTree2(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2 == NULL) return true;
if(pRoot1 == NULL) return false;
if(pRoot1->val != pRoot2->val) return false;
return DoesTree1HaveTree2(pRoot1->left, pRoot2->left) &&
DoesTree1HaveTree2(pRoot1->right, pRoot2->right);
}
};