本篇笔记,记录剑指offer
中的问题(不只是面试题)。
对某些面试题,同时也指出leetcode
对应题目的网址
:dagger:需要对文档进行补充,代码解释等
基本素质:基础知识、高质量代码、清晰的思路、优化效率的能力、综合能力
背景:在C/C++语言中用 (type) value(在C++还可以采用type(value))来进行显式类型转换(explicit type conversion),常常又被称为强制转换(cast投射/铸模)。这种转换的正确性完全掌握在程序员手中,传统上强制转换往往被过度使用,成为C++程序犯错的一个主要根源。 为了减少强制转换的副作用,并且在查错时使程序员能够快速定位(总是最值得怀疑的)强制转换,在标准C++中新增加了4个关键字*_cast,用来提倡一种全新的C++显式转换语法: *_cast
问:C++中,有哪四个与类型转换相关的关键字?
答:static_cast, const_cast, dynamic_cast, reinterpret_cast
static_cast, 运算符完成相关类型之间类型的转换
静态转换,在编译处理期间
C++内置基本数据类型之间的转换。但是没有运行时类型的检测来保证转换的安全性。
用法:
l = static_cast<long>(i);//i是整型,l是长整型。
f = static_cast<float>(i);//在传统方法下,可以进行隐式转换。
i = static_cast<int>(l);//i是整型,l是长整型,f是浮点型,c是char。
i = static_cast<int>(f);// i = l,i = f会告警,且会丢失数据。
c = static_cast<char>(i);//i = (int)l,不会告警,但是程序debug困难。
const_cast
去常转换,编译时执行
const_cast操作不能在不同的种类间转换。相反,它仅仅把它作用的表达式转换成常量。它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。
用法:
const int i = 0;
int *pi;
pi = &i; // 错误
pi = (int *)&i; // 被反对
pi = const_cast<int *>(&i); // 完美,将常量指针转换成非常量指针
long *pl = const_cast<long *>(&i); // 错误,要求是同数据类型
volatile int k = 0;
int *pk = const_cast<int *>(&k); // 正确
dynamic_cast => dynamic_cast
如果 type-id 是类指针类型,那么expression也必须是一个指针,如果 type-id 是一个引用,那么 expression 也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
dynamic_cast(动态转换):一种安全的向下类型转换(downcast)操作,用于在一个类继承层次上向下移动。
class Pet {……};
class Dog : public Pet {……};
class Cat : public Pet {……};
……
Pet *pPet = new Cat; // 向上的类型转换
Dog *pDog = dynamic_cast<Dog *>(pPet); // 类型错误,返回0(NULL)
Cat *pCat = dynamic_cast<Cat *>(pPet); // 类型正确,返回指针
Cat *pCat = static_cast<Cat *>(pPet); // 正确,减少运行时的开销
reinterpret_cast
使用reinterpret_cast通常是一种不明智且不方便的编程方式。但是在必须使用时,它也是非常有用的。
type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。
const int sz = 100; // 定义数组大小,标准C++提倡用常型变量(而不是常数或
// 符号常量宏)
struct X {int a[sz];}; // 只包含一个整数数组的结构
X x; // 定义结构变量,此时结构中的数组元素的值无意义(需要初始化)
int *px = reinterpret_cast<int *> (&x); // 为了初始化,先把结构转化为int数组
for (int *i = px; i < px + sz; i++) *i = 0; // 将每个数组元素的值初始化为0
print(reinterpret_cast<X *> (px)); // 重新转换成结构指针,以便使用
// 也可以直接使用原来的标识符x
// 此语句相当于print(&x);
参考资料: C++中,有哪四个与类型转换相关的关键字 C++中,有哪4个与类型转换相关的关键字?
1问:一个空类型里面没有定义任何成员变量、成员函数,对该类型的求sizeof,得到的结果是什么?
答:为1,但是也根据编译器改变,vs当中是1。
解释:按理应该求得sizeof为0,但是在声明该类型的时候,他在内存中必须有一定的空间,否则无法使用这些实例。
2问:如果添加构造函数和析构函数呢?
答:还是1,调用这两个函数只需要两个函数的地址,而他们只和类型相关,和实例无关。
3问:如果上面的析构函数是虚函数呢?
答:如果是虚析构函数,那么会为该类型生成虚函数表,并在该类型当中添加一个指向虚函数表的指针。32位系统中一个指针占4字节,sizeof=4。64位系统中sizeof的得到的值位8。
拷贝构造函数的传入参数必须是A(const&A a), 参数必须当成常量引用
题目:为类型CMyString
的声明添加赋值运算符函数。
class CMyString
{
public:
CMyString(char* pData=nullptr);
CMyString(const CMyString& str);
/* 常规正确写法
CMyString& CMyString::operator == (const CMyString& str) //注意返回当前类型以支持连续赋值
{
if(this == &str) //注意判断输入的与当前的是不是同一个对象
return *this;
delete [] this; //注意删除当前空间之后在进行赋值
m_pData = nullptr;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData,str.m_pData); //学会使用strcpy
return *this; //记得返回当前
}
*/
/*
1. 较好的方法是,先申请内存再删除当前空间的内存,这样可以避免内存不足异常。
2. 或者,先创建临时实例,在交换临时实例和原来的实例。
*/
~CMyString(void);
private:
char* m_pData;
}
实现一:线程不安全
class Singleton{
public:
static Singleton* getInstance(){
if(m_instance == nullptr){
m_instance = new Singleton();
}
return m_instance;
}
private:
Singleton();
Singleton(const Singleton& other);
static Singleton* m_instance;
};
Singleton* Singleton::m_instance=nullptr;
/*
正常情况下,如果线程A调用getInstance()时,将m_instance 初始化了,那么线程B再调用getInstance()时,就不会再执行new了,直接返回之前构造好的对象。然而存在这种情况,线程A执行m_instance = new Singleton()还没完成,这个时候m_instance仍然为nullptr,线程B也正在执行m_instance = new Singleton(),这是就会产生两个对象,线程A和B可能使用的是同一个对象,也可能是两个对象,这样就可能导致程序错误,同时,还会发生内存泄漏。
*/
实现二:线程安全,锁代价高
Singleton* Singleton:getInstance(){
Lock(); //每次都会lock锁代价高
if(m_instance == nullptr);
m_instance = new Singleton;
Unlock();
return m_instance;
}
实现三:线程安全,低锁代价
Singleton* Singleton:getInstance(){
if(m_instance == nullptr){
Lock();
if(m_instance == nullptr);
m_instance = new Singleton;
Unlock();
}
return m_instance;
}
实现四:解决方案三的bug,java/C#提出volatile,也就是把m_instanced用volatile声明,避免reorder。
/*
这个方法没有进行深入研究
*/
//C++ 11版本之后的跨平台实现
// atomic c++11中提供的原子操作
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;
/*
* std::atomic_thread_fence(std::memory_order_acquire);
* std::atomic_thread_fence(std::memory_order_release);
* 这两句话可以保证他们之间的语句不会发生乱序执行。
*/
Singleton* Singleton::getInstance() {
Singleton* tmp = m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);//获取内存fence
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(m_mutex);
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);//释放内存fence
m_instance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
实现五:pthread_once函数
在linux中,pthread_once()
函数可以保证某个函数只执行一次。
声明: int pthread_once(pthread_once_t once_control, void (init_routine) (void));
功能: 本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。
class Singleton{
public:
static Singleton* getInstance(){
// init函数只会执行一次
pthread_once(&ponce_, &Singleton::init);
return m_instance;
}
private:
Singleton(); //私有构造函数,不允许使用者自己生成对象
Singleton(const Singleton& other);
//要写成静态方法的原因:类成员函数隐含传递this指针(第一个参数)
static void init() {
m_instance = new Singleton();
}
static pthread_once_t ponce_;
static Singleton* m_instance; //静态成员变量
};
pthread_once_t Singleton::ponce_ = PTHREAD_ONCE_INIT;
Singleton* Singleton::m_instance=nullptr; //静态成员需要先初始化
实现六:C++11版最简洁跨平台方案
使用局部静态变量
class Singleton{
public:
// 注意返回的是引用
static Singleton& getInstance(){
static Singleton m_instance; //局部静态变量
return m_instance;
}
private:
Singleton();
Singleton(const Singleton& other);
};
//模板类
template<typename T>
class Singleton
{
public:
static T& getInstance() {
static T value_; //静态局部变量
return value_;
}
private:
Singleton();
~Singleton();
Singleton(const Singleton&); //拷贝构造函数
Singleton& operator=(const Singleton&); // =运算符重载
};
int GetSize(arr[] a){
return sizeof(a);
}
int main(){
int data1[] ={1,2,3,4,5};
int size1 = sizeof(data1);
int * data2 = data1;
int size2 = sizeof(data2);
int size3 = GetSize(data1);
printf("%d, %d, %d",size1,size2,size3);
//判断输出的结果?
}
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
#if 0 //方法一:时间复杂度空间复杂度比较差
/**
* 采用排序遍历的方法
* 执行用时 :152 ms, 在所有 C++ 提交中击败了30.36%的用户
* 内存消耗 :16.3 MB, 在所有 C++ 提交中击败了13.75%的用户
*/
vector<int> dup;
if(nums.size()<2){
return dup;
}
sort(nums.begin(),nums.end());
vector<int>::iterator it;
for(it = nums.begin() + 1;it != nums.end();++it){
if((*it) == (*(it - 1))){
dup.push_back((*it));
}
}
return dup;
#endif
#if 1
/**
* 采用hashtable的方法
*
* 28/28 cases passed (92 ms)
* Your runtime beats 84.69 % of cpp submissions
* Your memory usage beats 13.88 % of cpp submissions (16.3 MB)
*/
vector<int> dup;
if(nums.size()<2){
return dup;
}
/**
* 解释:
* 需要一个辅助输出数组。
* 遍历元素,该元素-1下标位置数据修改为当前值的负数,如果便利到该元素对应下标的数据已经是负数了,说
* 明已经找到过一次了,便把他添加到输出数组当中
*
*
*/
vector<int> res;
for(int v:nums){
v = abs(v);
if(nums[v-1] < 0)
res.push_back(v);
else
nums[v-1] = -nums[v-1];
}
return res;
return dup;
#endif
}
};
解决该问题的关键是,从右上角开始找,因为右上角的数据!=目标数据的时候,大于target和小于target可以分成不同情况进行排除某行某列,从而不断进一步找到目标数,但是从左上角就无法分成两种情况。
#include <vector>
#include <iostream>
using namespace std;
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
/**
* 思路:从右上角开始查找,逐次排除某行某列。
* 如果大于target则剔除这一列,如果小于target则剔除这一行。
*
* [
* [1, 4, 7, 11, 15],
* [2, 5, 8, 12, 19],
* [3, 6, 9, 16, 22],
* [10, 13, 14, 17, 24],
* [18, 21, 23, 26, 30]
* ]
*
*
*/
if(matrix.empty()){
return false;
}
size_t col = matrix.at(0).size();
size_t row = matrix.size();
//cout <<"row:"<< row <<"col:"<<col<<endl;
int colptr = col -1;
int rowptr = 0;
bool found = false;
if(col > 0 && row > 0 ){
while (rowptr < row && colptr >= 0)
{
/* code */
if(target == matrix[rowptr][colptr]){
found = true;
break;
}
if(target > matrix[rowptr][colptr]){
rowptr++;
}else
{
colptr--;
}
}
}
return found;
}
};
题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
知识:从前往后替换的话,时间效率低(n2),需要重复遍历后面的字符。所以可以考虑从后面向前替换新增字符。
#include <string.h> #include <stdio.h> class Solution { public: void replaceSpace(char *str,int length) { if(str == nullptr || length < 0) // 错误输入处理 return; size_t count_space = 0; for (size_t i = 0; i < length; i++) { /* code */ if(*(str+i) == ' ') count_space++; } // info :printf("%d\n",count_space); char* retstr = new char[length + count_space * 2]; retstr[length + count_space * 2] = '\0'; /** * 执行从后替换逻辑 * */ // debug :length = 14 unsigned ptr = length + count_space * 2 - 1; for (size_t i = length -1 ; i <= ptr; i--) { // debug :printf("%s \n",str+i); /* code */ if( *(str + i) == ' ' ){ *(retstr + ptr) = '0'; ptr--; *(retstr + ptr) = '2'; ptr--; *(retstr + ptr) = '%'; ptr--; } else { /* code */ *(retstr + ptr) = *(str +i); ptr--; } } printf(" retstr is :%s \n",retstr); } };
void SortAges(int ages[],int lengh){
if(ages == nullptr || length <=0)
return;
const int olestAge = 99;
int timesOfAge[oldestAge + 1];
for(int i=0;i< length;++i){
timesOfAge[i] = 0;
}
for(int i=0;i<length;++i){
int age = ages[i];
if(age < 0 || age > oldestAge)
throw new std::exception("age out of range.");
++ timesOfAge[age];
}
int index = 0;
for(int i=0;i<=oldestAge; ++i){
for(int j=0;j<timesOfAges[i];++j){
ages[index] = i;
++ index;
}
}
}
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组
[0,1,2,4,5,6,7]
可能变为[4,5,6,7,0,1,2]
)。请找出其中最小的元素。
你可以假设数组中不存在重复元素。
#include <vector>
#include <iostream>
using namespace std;
class Solution {
public:
/**
* 用两个指针减少遍历的次数
*/
int findMin(vector<int>& nums) {
size_t leftPtr = 0;
size_t rightPtr = nums.size() -1;
size_t destinyPtr = 0;
//cout << "debug:: in the findMin function!"<<endl;
if(nums.size() < 1)
cerr << "Invalid Input arry" << endl;
if(nums.size()==1)
return nums[0];
while (nums[leftPtr] >= nums[rightPtr])
{
//cout << "debug:: still in the while!"<<endl;
/* code */
if(rightPtr - leftPtr == 1){
//如果两个指针之差为1则说明已经找到了最小值
destinyPtr = rightPtr;
break;
}
size_t mid = (rightPtr + leftPtr) / 2;
if(nums[mid]==nums[leftPtr] && nums[mid] == nums[rightPtr]){
//如果三个相等没法判断的情况
//采用顺序查找的方式
int min = nums[0];
for(size_t i=0;i<nums.size();++i){
if(min > nums[i]){
min = nums[i];
}
}
return min;
}
if(nums[mid] > nums[leftPtr]){
leftPtr = mid;
}
if(nums[mid] < nums[rightPtr]){
rightPtr = mid;
}
}
return nums[destinyPtr];
}
};
Leetcode
中对应:单词搜索
/*
* @lc app=leetcode.cn id=79 lang=cpp
*
* [79] 单词搜索
*/
// @lc code=start
#include <vector>
#include <string>
using namespace std;
/**
* 思路:回溯法。
* 87/87 cases passed (456 ms)
* Your runtime beats 9.21 % of cpp submissions
* Your memory usage beats 6.3 % of cpp submissions (160.1 MB)
*
*/
/*
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.
*/
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
size_t index = 0;
size_t row = board.size();
size_t col = board[0].size();
// 初始化visited矩阵
vector<bool> init_visited(col,false);
vector<vector<bool>> visited(row,init_visited);
bool haspath = false;
for(int i =0; i < row; ++i){
for(int j =0;j < col; ++j){
haspath = findWordCore(board,visited,row,col,word,0,i,j);
if(haspath){
return true;
}
}
}
return haspath;
}
bool findWordCore(
vector<vector<char>>& board,
vector<vector<bool>>& visited,
size_t rowtotal,
size_t coltotal,
string word,
size_t next_IndexInWord,
size_t next_row,
size_t next_col){
if(next_IndexInWord == word.size()){
return true;
}
bool hasPath = false;
if(
next_row < rowtotal &&
next_col < coltotal &&
board[next_row][next_col] == word[next_IndexInWord] &&
!visited[next_row][next_col]){
++ next_IndexInWord;
visited[next_row][next_col] = true;
hasPath = findWordCore(//网上搜索
board,
visited,
rowtotal,
coltotal,
word,
next_IndexInWord,
next_row,
next_col - 1
) || findWordCore(
board,
visited,
rowtotal,
coltotal,
word,
next_IndexInWord,
next_row,
next_col + 1
) || findWordCore(
board,
visited,
rowtotal,
coltotal,
word,
next_IndexInWord,
next_row - 1,
next_col
) ||findWordCore(
board,
visited,
rowtotal,
coltotal,
word,
next_IndexInWord,
next_row + 1,
next_col
);
if (!hasPath)
{
/* code */
--next_IndexInWord;
visited[next_row][next_col] = false;
}
}
// 放回当前子节点往后是否存在路径
return hasPath;
}
};
// @lc code=end
//#define ROBOTMOVERANGE
#ifdef ROBOTMOVERANGE
#include <iostream>
#include <vector>
#include <string>
using namespace std;
/**
* 当前代码没有经过测试
*
*
*/
class Solution
{
public:
size_t rangOfMove(
size_t threahold,
size_t rows,
size_t cols)
{
vector<bool> init_visit(cols,false);
vector<vector<bool>> visited (rows,init_visit);
int count = rangOfMoveCore(threahold,rows,cols,0,0,visited);
return count;
}
private:
/* data */
size_t rangOfMoveCore(
size_t threshold,
size_t rowstotal,
size_t colstotal,
size_t row,
size_t col,
vector<vector<bool>> &visited
){
int count = 0;
if(/*在可运动范围之内*/true)
{
visited[row][col] = true;
count = 1 + rangOfMoveCore(
threshold,rowstotal,colstotal,
row,col - 1,visited
) + rangOfMoveCore(
threshold,rowstotal,colstotal,
row,col + 1,visited
) + rangOfMoveCore(
threshold,rowstotal,colstotal,
row - 1,col,visited
) + rangOfMoveCore(
threshold,rowstotal,colstotal,
row + 1,col,visited
);
}
return count;
}
bool check(
size_t threshold,size_t rowstotal,
size_t colstotal,size_t row,size_t col,
vector<vector<bool>> visited){
if(row>=0 && col >= 0 &&
row < rowstotal && col < colstotal &&
getDigitSum(row) + getDigitSum(col) <= threshold &&
!visited[row][col])
{
return true;
}
return false;
}
int getDigitSum(int number){
int sum = 0;
while (number > 0)
{
/* code */
sum += number % 10;
number /= 10;
}
return sum;
}
};
#define CUT_ROPE
#ifdef CUT_ROPE
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
class Solution
{
public:
int cut_ropeByBP(int n)
{
if (2 > n)
{
return 0;
}
else if (2 == n)
{
return 1;
}
else if (3 == n)
{
return 2;
}
// 开始做动规
vector<int> pd(n + 1, 0);
pd[0] = 0;
pd[1] = 1;
pd[2] = 2;
pd[3] = 3; //切3为一段的时候,切下来的是3。
int max = 0;
for (int i = 4; i <= n; ++i)
{
max = 0;
for(int j=0;j <= i/2 ;++j){
int p = pd[j] * pd[i-j];
if (max < p)
{
/* code */
max = p;
}
//cout<<"debug: max=" << max << " index=" << i << endl;
pd[i] = max;
}
}
//cout<<"debug: " << n << endl;
max = pd[n];
return max;
}
int cut_ropeByGreedy(int length)
{
if (2 > length)
{
return 0;
}
else if (2 == length)
{
return 1;
}
else if (3 == length)
{
return 2;
}
int timesOf3 = length / 3;
if(length - timesOf3 * 3 == 1){
timesOf3 -=1;
}
int timesOf2 = (length - timesOf3 * 3) / 2;
return (int)pow(3,timesOf3) * (int)(pow(2,timesOf2));
}
};
/*
* @lc app=leetcode.cn id=191 lang=cpp
*
* [191] 位1的个数
*/
// @lc code=start
#include <cstdint>
#include <iostream>
using namespace std;
/**
*
* 601/601 cases passed (0 ms)
* Your runtime beats 100 % of cpp submissions
* Your memory usage beats 58.53 % of cpp submissions (8.2 MB)
*
*/
class Solution {
public:
int hammingWeight(uint32_t n) {
/**
* n-1, 把所有该为右边的1都变为零。这个过程能剔除一个一。
* 右边都变成0,可以用n&(n-1) 做到
*/
int count = 0;
while (n)
{
/* code */
++ count;
n = (n-1) & n;
}
return count;
}
};
// @lc code=end
/*
* @lc app=leetcode.cn id=50 lang=cpp
*
* [50] Pow(x, n)
*/
// @lc code=start
/**
* 采用 >> 1 的方式,减少运行时间
* 304/304 cases passed (4 ms)
* Your runtime beats 71.5 % of cpp submissions
* Your memory usage beats 93.42 % of cpp submissions (8.2 MB)
*/
#include <iostream>
using namespace std;
class DivZeroException {
const char* what() {
return "Math Error, /0";
}
};
class Solution {
public:
double myPow(double x, int n) {
double result = 1.0;
if (n < 0 && x - 0.0 < 0.0005f && x - 0.0 > -0.0000f) {
throw DivZeroException();
}
if (n == INT_MIN) {
//避免 INT_MIN 的相反数越界的问题
++n;// 不越界
n = -n;//算正数
// 后边又乘了两个x是因为上边的abs(n) 本来应该是偶数的,但是自己做了处理后相当于少了2个x
// result = myPow(x * x, abs(n) / 2);
result = this->unsignedPow(x * x * x * x, n / 4) ;
return 1.0 / result;
}
if (n < 0) {
//需要算倒数
unsigned int absEx = (unsigned int)(-n);
result = this->unsignedPow(x, absEx);
result = 1 / result;
}
else if (n > 0)
{
/* code */
unsigned int absEx = (unsigned int)n;
result = this->unsignedPow(x, absEx);
}
else
{
/* code */
return 1.0f;
}
return result;
}
double unsignedPow(double x, unsigned int n) {
if (n == 0)
return 0;
else if (n == 1) {
return x;
}
double result = unsignedPow(x, n >> 1);
result *= result; // 计算二次方
if ((n & 0x01) == 1) { // 如果次方为奇数,则再最后输出的时候需要 * x;
result *= x;
}
return result;
}
};
// @lc code=end
#define PRINTONE2NBIT_NUMBER
#ifdef PRINTONE2NBIT_NUMBER
#include <iostream>
#include "stdio.h"
#include <cstring>
using namespace std;
class Solution
{
/* data */
/**
* 用string实现大数的输出。
*/
public:
void print1ToMaxOfNDigits(int n){
if(n <= 0){
return;
}
// printf("get into main function\n");
char* number = new char[n +1];
// printf("start init\n");
memset(number,'0',n);//每一位复制数字零
number[n]='\0';//最后一位赋值结束符
// printf("init finished\n");
int calcount = 0;
while (!incrementNumber(number) )
{
/* code */
printf("now the number is:");
printf("%s\n",number);
printf("standard output: ");
printNumberWithout0(number);
printf("\n");
// calcount ++;//只是为了防止越界
// if(calcount > 100000000){
// break;
// }
}
// printf("whole function finished");
return;
}
private:
void printNumberWithout0(char* n){
size_t strLength = strlen(n);
bool isThefirstZero = true;
for(size_t i=0; i <= strLength; ++i){
if(isThefirstZero){
if( n[i] != '0'){
isThefirstZero = false;
printf("%c",n[i]);
}
}else{
printf("%s",n + i);
break;
}
}
}
bool incrementNumber(char * incrementNumber){
// printf("start increase function...\n");
size_t strLength = strlen(incrementNumber);
//int bitNumber = 0;
bool overflow = false;
int takeover = 0;
int afterAdd = 0;
// printf("start loop for add & check takeover\n");
for (int i = strLength -1 ; i >= 0; --i)
{
// printf("loop i = %d\n",i);
afterAdd = incrementNumber[i] - '0' + takeover;
takeover = 0;
/* code */
if(i == strLength -1){//如果是第一位则要+1
afterAdd++;
}
if(afterAdd == 10){
if (i ==0){ // 如果在最高位的时候进位的话,说明溢出了
overflow = true;
}
else{
takeover = 1;
incrementNumber[i] = '0';
afterAdd = 0;
}
}
else if (afterAdd <= 9){
incrementNumber[i] = '0' + afterAdd;
}
}
// printf("ending increase function...");
return overflow;
}
};
链表
hash表实现
二叉树
红黑树
B+ tree