c++后台开发面试常见知识点总结(六)算法手写
- 链表倒转 leetcode-206
- 连续子数组最大和问题(和最大的连续子序列的和) leetcode-53
- 输出字符串中最长的回文子串长度? leetcode-5
- 一个字符串,求最长无重复子串的长度? leetcode-3
- 最长递增子序列 leetcode-300
- 反转一个字符串。。。。。。(手写代码) leetcode-344
- 数组中存在一个大于n/2次的数,如何以最优方法查找它?LeetCode 169 \ 229
- 一个字符串中{} [ ] ()匹配问题 LeetCode 20
- 一个数组,只有一个数字出现奇数次,其余数字出现偶数次 LeetCode 136
- 给定一个ip地址,编码使得ip和32位整数呈双射关系 LeetCode 93
- 求一个数组逆序对的个数 LeetCode 629
- 1个32位整数,计算二进制格式下有多少个1 LeetCode 191
- 最小生成树与并查集 leetcode684,685, 721
- 比较两二叉树是否相同(手写代码)LeetCode 100
- 手写判断大小端的代码
- 单链表找倒数第n个节点 LeetCode 19
- 把一颗二叉树原地变成一个双向链表? 114
- 判断一个无符号的整数是不是2的n次方? 231
- int atoi(char *str)? 8
- 栈的getmin()操作 O(1) 155
- 用栈实现队列,用队列实现栈?232 225
- 实现strstr函数 28
- 整数a和b,求a的b次方的最后三位数
- 算法题:将字符串转换成人民币大写(半小时后发邮箱)
- 如何删除map中的奇数节点
- 恢复翻转数组
- 二分法
- 排序
- 手写String
- memcpy函数的实现
- strcpy函数的实现
- BST的第K小的节点 230
- 判断链表是否有环,如果有,返回环的入口节点;求环的长度 141
- 求一个数组逆序对的个数 629
- 翻转数组和恢复翻转数组
- 删除单链表中间节点
- 判断两个单链表是否相交
- r行c列的0,1数组,找到最大的全为1的正方形?
- 连续子数组最大和问题(和最大的连续子序列的和)
- excel中,标志列的如AA,AZZ ,BS,求这些列到底是第几列
- 二叉树两个节点的最近公共祖先
- 去掉字符串中的空格字符
- 删除字符串开始和结尾处的空格,并将中间的多个连续的空格合并成一个
- char *s1, const char *s2,删除s1中s2出现过的字符
- 单链表判环
- 判断一个数是不是回文数
- 求一个集合的所有子集,递归实现,非递归实现
- 旋转有序数组的二分查找
- 删除数组中的重复元素
- 实现一个计算器计算简单的表达式字符串
- memcopy和memove
- 微信小程序团队一共有 n 名成员,决定出去秋游,在海边遇到出租摩托艇的杰克马
- 给定一个二叉树,节点值为0-9, LeetCode 129
- 写一个二叉树翻转,然后写个测试
- trcpy安全性,如何实现安全,strnpy,写一下并测试,
- 写sql语句(A表存储有每个电话号码当月通话记录,表B是电话号码集合,求表B每个号码通话次数)
- 如何设计一个好的字符串hash函数
- 两字符串最长公共子串, 最长公共子序列
- 打印二叉树每层最右边的节点 层序遍历 LeetCode 199
- 顺时针回形打印矩阵的元素 LeetCode 54
- 判断在一个矩阵中是否存在一条包含某字符串所有字符的路径 LeetCode 79
- 3sum 数组中三数之和为0的所有三元组 leetcode 15
- 判断一个字符串是不是两个有序的字符串交错组成的。 Leetcode 97
- 编程题:递增数组中找两个数和为某个固定值。设计测试用例 Leetcode 1
- 给你一个数组和数组元素的个数,求平均值。
- 两个非常大的数相加 Leetcode 415
- 手写下单例模式?
- 链表倒转
从尾到头打印链表(使用栈或者使用递归)
链表倒转
typedef struct ListNode
{
int data;
ListNode *next;
};
ListNode* reverseList1(ListNode *head)
{
if (head == NULL)
return head;
ListNode* dummy = new ListNode;
dummy->data = -1;
dummy->next = head;
ListNode *Cur = dummy->next;
ListNode *tmp = Cur->next;
while (tmp != NULL) {
Cur->next = tmp->next;
tmp->next = dummy->next;
dummy->next = tmp;
tmp = Cur->next;
}
Cur->next = NULL;
return dummy->next;
}
- 连续子数组最大和问题(和最大的连续子序列的和)
- 输出字符串中最长的回文子串长度?
https://blog.csdn.net/h_xy_zwb/article/details/64124271
DP:O(n^2)
string
longestPalindrome(string s) {
int len=s.size();
vector<vector<int>>
flag(len,vector<int>(len,0));
int maxres=0,idx=0;
for(int i=0;i<len;i++){
for(int
j=0,k=i;j<len&&k<len;j++,k++){
if(k==j) flag[j][k]=1;
else
if(s[k]==s[j]&&j+1==k) flag[j][k]=2;
else
if(s[k]==s[j]&&flag[j+1][k-1]>0) flag[j][k]=flag[j+1][k-1]+2;
else flag[j][k]=0;
if(flag[j][k]>maxres){
maxres=flag[j][k];
idx=j;
}
}
}
return s.substr(idx,maxres);
}
一个字符串,求最长无重复子串的长度?
最长递增子序列:
思想:在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。
- 手写下单例模式?
- class singleton{
- protected:
- singleton(){}
- private:
- static
singleton* p; - public:
- static
singleton* getInstance(); - }
- singleton* singleton::p = new singleton();
- singleton* singleton::getInstance(){
- return
p; - }
- 写个string类
- 反转一个字符串。。。。。。(手写代码)
剑指58
.对于string类型的:使用algorithm中的reverse函数,reverse(s.begin(),s.end());
对于用char定义的字符串:使用string.h中的strrev函数,char s[]="123456";//不能是string类型;strrev(s);
实现:设置两个指针,一头一尾,往中间移动;
- 数组存中在一个大于n/2次的数,如何以最优方法查找它?
- int MoreThanHalfNum(int *arr, int len)
- 2 {
- 3 int result = arr[0];
- 4 int count = 1;
- 5
- 6 for(int i = 1; i < len; ++i)
- 7 {
- 8 if(arr[i] == result)
- 9 count ++;
- 10 else if(count == 0)
- 11 {
- 12 result = arr[i];
- 13 count = 1;
- 14 }
- 15 else
- 16 count --;
- 17 }
- 18 return result;
- 19 }
一个字符串中{} [ ] ()匹配问题
bool isValid(string s) {
std::stack<char> st;
for(int i = 0; i < s.size(); ++i)
{
char ch = s.at(i);
if(ch == '(' || ch == '[' || ch == '{')
st.push(ch);
else if(st.size() > 0 && ((ch == ')' && st.top() == '(') || (ch == ']' && st.top() == '[') || (ch == '}' && st.top() == '{')))
st.pop();
else
return false;
}
return st.size() == 0;
}
- 一个数组,只有一个数字出现奇数次,其余数字出现偶数次,如何得到这个数字?如果出现奇数次的数字有2个呢?
可以用位运算实现,如果将所有所有数字相异或,则最后的结果肯定是那两个只出现一次的数字异或的结果,所以根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据
这样继续对每一半相异或则可以分别求出两个只出现一次的数字
- 给定一个ip地址,编码使得ip和32位整数呈双射关系
int IpToInt(string s)
{
int ret=0; int num=0;
for(int
i=0;i<s.size();i++)
{
if(s[i]!='.')
{num=num*10+(s[i]-'0');}
else
{
cout<<num<<endl;
ret=ret<<8;
ret+=num;
cout<<ret<<endl;
num=0;
}
}
ret=ret<<8;
ret+=num;
return
ret;
}
- 求一个数组逆序对的个数
基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目。统计逆序对时,先统计子数组内部的逆序对的数目,再统计相邻子数组的逆序对数目。
- 1个32位整数,计算二进制格式下有多少个1,不通过循环怎么做
通过n与n-1相& 清楚n最右边的1;
int BitCount(int n){
int c=0;//计数器
while(n){
n&=(n-1);
++c;
}
return c;
}
- 算法 最小生成树
Prim+ Kruskal算法
https://www.cnblogs.com/GHzz/p/9148279.html
- 比较两二叉树是否相同(手写代码)。现在我才明白,大概是在考我用递归怎么遍历树,我当时写的居然是以按层遍历的方式去遍历树,
递归
手写判断大小端的代码
https://blog.csdn.net/kit_9875507/article/details/44264663
大小端的本质就是不同的存储方式
大端模式:字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
小端模式:字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
根据这个特性,假设我们初始化了一个int变量i为0x12345678,其地址为0x100,根据定义在小端模式下
0x100一个字节内的值为0x78,类推0x101=>0x56,0x102=>0x34,0x103=0x12,根据这个编程如下
- int checkSystem(void)
- {
- int i = 0x12345678;
- char *c = &i;
- return ((c[0] == 0x78) && (c[1] == 0x56) && (c[2] == 0x34) && (c[3] == 0x12));
- }
int main(void)
{
if(checkSystem())
printf("little
endian\n");
else
printf("big
endian\n");
return 0;
}
单链表找倒数第n个节点,说所有你能想到的方法。
方法一:遍历链表,记录链表的长度total,再次遍历链表,第total - N - 1个节点就是查找结果,需要遍历两次链表
方法二:使用两个指针,通过移动指针,遍历一次链表,p指针首先移动n-1步,然后p和q同时移动,直到p.next == null,此时q所指向的节点就是所求
怎么把一颗二叉树原地变成一个双向链表?
转换成有序双向链表:https://www.cnblogs.com/wanglei5205/p/8780086.html
怎么判断一个无符号的整数是不是2的n次方?
思路:一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0。把这个整数与这个整数减去1之后进行与运算,那么这个整数当中唯一的
1会变为0,这个整数也变为0;
- int atoi(char *str)?
- //atoi
- enum ={Invalid = 0, Valid};
- bool errno = Invalid;
- int atoi(const
char * str) - {
- long long num = 0; //point1:可能溢出,所以用long long存
- errno = Invalid;//初始设输入为不合法输入
- if (str!=nullptr && *str != '\0')
//point2://考虑了空串和空指针 - {
- bool minus = false;
- if (*str == '+')
- {
- ++str;
- }
- else if (*str == '-')
- {
- ++str;
- minus = true;
- }
- if (*str!='\0') //只有符号,Invalid
- atoiCore(str, minus, num);
- }
- return (int)num; //已经检查过溢出,保证了num在int范围内
- }
- void
atoiCore(const char *str, bool minus, long long &num) - {
- while ('\0' != *str)
- {
- if (*str >= '0' && *str
<= '9') - {
- num = num*10 + (*str - '0');
- ++str;
- if ((!minus && num >
0x7FFFFFFF)||(minus && (-num) < (signed int)0x80000000))//输入溢出 - {
- errno = Invalid;
- num = 0;
- return;
- }
- }
- else
//输入非法字符 - {
- errno = Invalid;
- num = 0;
- return;
- }
- }
- if (minus)
- num = -num;
- errno = Valid; //标志输入合法
- }
- 栈的getmin()操作 O(1)
template <typename T> class
NewStack
{
private :
std::stack<T> stack_data;
std::stack<T> stack_support;
public:
NewStack();
~NewStack();
void push( T value)
{
stack_data.push (value);
if (stack_support.size()==0 || stack_support.top()>value)
stack_support.push(value);
else:
stack_support.push
(stack_support.top());
}
void pop()
{ if (stack_data.size()>0 &&
stack_support.size()>0)
{
stack_data.pop;
stack_support.pop;
}
}
T min()
{
if (stack_data.size()>0 && stack_support.size()>0)
{
return stack_support.top();
}
}
- 用栈实现队列,用队列实现栈?
使用队列实现栈:
class MyStack {
public:
MyStack() {
}
void
push(int x) {
queue<int> temp; //建立一个辅助队列
while(q.empty() == false){ //将队列q中所有元素存入辅助队列中
temp.push(q.front());
q.pop();
}
q.push(x); //向队列中压入元素,放在队首
while(temp.empty() == false){ //逐个将辅助队列中的元素送回队列q中
q.push(temp.front());
temp.pop();
}
}
int
pop() {
int a = q.front(); //将队列首元素返回
q.pop(); //删除队首
return a;
}
int
top() {
return q.front(); //返回队首
}
bool
empty() {
return q.empty();
}
private:
queue<int> q;
};
用栈实现队列
class MyQueue {
public:
MyQueue() {
}
void
push(int x) { //将元素放到栈底
stack<int> temp;
while(s.empty() == false){
temp.push(s.top());
s.pop();
}
s.push(x);
while(temp.empty() == false){
s.push(temp.top());
temp.pop();
}
}
int
pop() {
int a = s.top();
s.pop();
return a;
}
int
peek() {
return s.top();
}
bool
empty() {
return s.empty();
}
private:
stack<int> s, temp;
};
实现strstr函数
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
整数a和b,求a的b次方的最后三位数
.
- 算法题:将字符串转换成人民币大写(半小时后发邮箱)
https://blog.csdn.net/forlove_you/article/details/51248978
- 如何删除map中的奇数节点
遍历删除,考虑迭代器失效问题
- for(ITER
iter=mapTest.begin();iter!=mapTest.end();++iter)
{ if(iter指向的元素是奇数)
mapTest.erase(iter);
} //错误,erase会让迭代器会失效!
- for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{ if(iter指向的元素是奇数)
mapTest.erase(iter++);//正确,iter值传递之后,再++;
}
- for(ITER
iter=mapTest.begin();iter!=mapTest.end();)
{ if(iter指向的元素是奇数)
iter=mapTest.erase(iter);//
erase() 成员函数返回下一个元素的迭代器
}
翻转数组和恢复翻转数组
找分界点:找分界点可以用一个指针来,遍历找到第一个下降的点,如果没有找到,说明数组已经是排好的。
二分法:
普通
int binary_search(int*arr,int l,int h,int key){
while (l <= h){
int m = l + (h - l)
/ 2;
if (arr[m] == key)
return m;
else if (arr[m] >
key)
h = m - 1;
else l = m + 1;
}
return -1;
}
lower_bound
int binary_search(int*arr, int l, int h, int key){//找到第一个插入的位置
while (l <h){
int m = l + (h - l)
/ 2;
if (arr[m] >=
key)
return h=m;
else l = m + 1;
}
}
排序
插入排序
void insert_sort(int* arr, int l, int h) {
for (int i = l + 1; i <=
h; ++i)
for (int j = i; j
> 0; --j){
if (arr[j]
< arr[j - 1]){
iter_swap(&arr[j],
&arr[j-1]);
}
}
}
快速排序
int partition(int* arry, int l, int h){
int pivot = arry[h];
while (true){
while (arry[l] <
pivot) ++l;
while (arry[h] > pivot)
--h;
if (!(l < h))
return l;
iter_swap(&arry[l],
&arry[h]);
++l;
--h;
}
}
void quick_sort(int* arr, int l, int h) {
if (l >= h) return;
int m = partition(arr, l,
h);
quick_sort(arr, l, m-1);
quick_sort(arr, m , h);
}
堆排序
void percDown(int* arr, int l, int h, int k) {
int child, tmp;
for (tmp = arr[k]; (k - l) *
2 + l + 1 <= h; k = child) {
child = (k - l) * 2
+ l + 1;
if (child + 1 <=
h && arr[child] < arr[child + 1]) ++child;
if (arr[child] >
tmp) arr[k] = arr[child];
else break;
}
arr[k] = tmp;
}
void heap_sort(int* arr, int l, int h) {
for (int i = l + (h - l) /
2; i >= l; --i) {
percDown(arr, l, h,
i);
}
for (int i = h; i >= l;
--i) {
int tmp = arr[l];
arr[l] = arr[i];
arr[i] = tmp;
percDown(arr, l, i -
1, l);
}
}
归并排序
void merge_sort(int* arr, int l, int h) {
if (l == h) return;
int m = l + (h - l) / 2;
merge_sort(arr, l, m);
merge_sort(arr, m + 1, h);
int * tmp = new int[h - l +
1];
int i = l, j = m + 1, k = 0;
while (i <= m &&
j <= h) {
if (arr[i] <= arr[j]) tmp[k++] = arr[i++];
else tmp[k++] =
arr[j++];
}
while (i <= m) tmp[k++] =
arr[i++];
while (j <= h) tmp[k++] =
arr[j++];
for (int i = l; i <= h;
++i) {
arr[i] = tmp[i - l];
}
delete []tmp;
}
冒泡排序
void bubble_sort(int* arr, int l, int h) {
for (int i = l; i <= h;
++i) {
for (int j = l; j
<= h - i + l - 1; ++j) {
if (arr[j]
> arr[j + 1]) {
int
tmp = arr[j];
arr[j]
= arr[j + 1];
arr[j
+ 1] = tmp;
}
}
}
}
选择排序
void select_sort(int* arr, int l, int h) {
for (int i = l; i <= h;
++i) {
int id = i;
for (int j = i + 1;
j <= h; ++j) {
if (arr[j]
< arr[id]) {
id
= j;
}
}
int tmp = arr[i];
arr[i] = arr[id];
arr[id] = tmp;
}
}
手写String
class String{
public:
String(const char *str = NULL); //普通构造函数
String(const String &other); //拷贝构造函数
String & operator=(String
&other) ; //赋值函数
~String(void); //析构函数
private: char* m_str;
};
//普通构造函数
String::String(const char* str){
if(str==NULL) //如果str为NULL,存空字符串{
m_str = new
char[1]; //分配一个字节
*m_str = ‘\0′; //赋一个’\0′
}else{
str = new
char[strlen(str) + 1];//分配空间容纳str内容
strcpy(m_str, str); //复制str到私有成员m_str中
}
}
//析构函数
String::~String(){
if(m_str!=NULL) //如果m_str不为NULL,释放堆内存{
delete [] m_str;
m_str = NULL;
}
}
//拷贝构造函数
String::String(const String &other){
m_str = new
char[strlen(other.m_str)+1]; //分配空间容纳str内容
strcpy(m_str, other.m_str); //复制other.m_str到私有成员m_str中
}
//赋值运算符函数
String & String::operator=(String
&other){
if(this == &other) //若对象与other是同一个对象,直接返回本{
return *this
}
delete [] m_str; //否则,先释放当前对象堆内存
m_str = new
char[strlen(other.m_str)+1]; //分配空间容纳str内容
strcpy(m_str, other.m_str); //复制other.m_str到私有成员m_str中
return *this;
}
memcpy函数的实现
void *memcpy(void *dest, const
void *src, size_t count) {
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
strcpy函数的实现
char *strcpy(char *dst,const
char *src) {
assert(dst != NULL
&& src != NULL);
char *ret = dst;
while((* dst++ = * src++) != '\0') ;
return ret;
}
BST的第K小的节点
http://www.cnblogs.com/grandyang/p/4620012.html
判断链表是否有环,如果有,返回环的入口节点;求环的长度
思路:采用两个指针walker和runner,walker每次移动一步而runner每次移动两步。当walker和runner第一次相遇时,证明链表有环 ;然后采用两个指针,一个从表头出发,一个从相遇点出发,一次都只移动一步,当二者相等时便是环入口的位置;
ListNode
*detectCycle(ListNode *head) {
auto walker = head;
auto runner = head;
while(runner &&
runner->next)//设置快慢指针,并找到相遇点
{
walker = walker->next;
runner = runner->next->next;
if(walker == runner)
break;
}
if(!runner || !runner->next) //单链表无环
return nullptr;
auto headWalker = head;//从头节点出发
auto crossWalker = walker; //从相遇点出发
while(headWalker != crossWalker)
{
headWalker = headWalker->next;
crossWalker = crossWalker->next;
}
return headWalker; //环的入口点
}
- 求一个数组逆序对的个数
基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目。统计逆序对时,先统计子数组内部的逆序对的数目,再统计相邻子数组的逆序对数目。
翻转数组和恢复翻转数组
找分界点:找分界点可以用一个指针来,遍历找到第一个下降的点,如果没有找到,说明数组已经是排好的。
给定链表头指针,中间结点的指针,如何删除单链表中间节点
快慢指针找中间值,
https://blog.csdn.net/cherrybomb1111/article/details/79803972
判断两个单链表是否相交,相交则找出两个链表的第一个公共子节点
思路1:分别遍历两个链表,得到分别对应的长度。然后求长度的差值,把较长的那个链表向后移动这个差值的个数,然后一一比较即可。
思路2:让两个指针分别从两条链表的开头开始往后遍历,当其中一条遍历到末尾时,我们将其跳到另一个条链表的开头继续遍历,一直遍历到两个指针相等为止。相等只有两种情况,一种情况是在交点处相遇,另一种情况是在各自的末尾的空节点处相等。,
为什么一定会相等呢,因为两个指针走过的路程相同,是两个链表的长度之和,所以一定会相等。
ListNode *getIntersectionNode(ListNode
*headA, ListNode *headB) {
if (!headA || !headB) return NULL;
ListNode *a = headA, *b = headB;
while (a != b) {
a = a ? a->next : headB;
b = b ? b->next : headA;
}
return a;
}
r行c列的0,1数组,找到最大的全为1的正方形?
https://blog.csdn.net/nk_test/article/details/48901853
- 连续子数组最大和问题(和最大的连续子序列的和)
- excel中,标志列的如AA,AZZ ,BS,求这些列到底是第几列。26进制转换问题:
- Int transfer(const string&
s){ - int res=0;
- for(int
i=0;i<s.length();i++){ - result=(result*26+(s[i]-'a'+1));
- }
- return res;
- }
二叉树两个节点的最近公共祖先,没答出来
https://www.cnblogs.com/grandyang/p/4641968.html
去掉字符串中的空格字符
https://blog.csdn.net/qian2213762498/article/details/81705647
void
trim(string &s)
{
int index = 0;
if( !s.empty())
{
while( (index = s.find(' ',index)) != string::npos)
{
s.erase(index,1);
}
}
}
删除字符串开始和结尾处的空格,并将中间的多个连续的空格合并成一个。
void
FormatString(char str[], int len)
{
if(str
== NULL || len <= 0)
return;
int i = 0, j = 0;
while(str[i]
== ' ')//开头的空格
i++;
while(str[i]
!= '\0')
{
if(str[i]
== ' ' && (str[i+1] == ' ' || str[i+1] == '\0'))
{
//中间或者结尾的空格
i++;
continue;
}
str[j++]
= str[i++];
}
str[j]
= '\0';
}
char *s1, const char *s2,删除s1中s2出现过的字符
思路:用一个256大小的数组,每个表示字符的状态,把s2读一遍,把每个字母对应的数字变为1表示存在,然后遍历s1,把状态为1的删掉
https://blog.csdn.net/m0_38099899/article/details/81231886
单链表判环
设两个指针,一个每次走一步的慢指针和一个每次走两步的快指针,如果链表里有环的话,两个指针最终肯定会相遇。
是不是:bool hasCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}
找环入口:ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) break;
}
if (!fast || !fast->next) return
NULL;
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return fast;
}
判断一个数是不是回文数
bool
isPalindrome(int x) {
if (x < 0 || (x % 10 == 0 &&
x != 0)) return false;
int revertNum = 0;
while (x > revertNum) {
revertNum = revertNum * 10 + x %
10;
x /= 10;
}
return x == revertNum || x == revertNum
/ 10;
}
http://www.cnblogs.com/grandyang/p/4125510.html
求一个集合的所有子集,递归实现,非递归实现
http://www.cnblogs.com/grandyang/p/4309345.html
vector<vector<int>
> subsets(vector<int> &S) {
vector<vector<int> >
res(1);
sort(S.begin(), S.end());
for (int i = 0; i < S.size(); ++i) {
int size = res.size();
for (int j = 0; j < size; ++j) {
res.push_back(res[j]);
res.back().push_back(S[i]);
}
}
return res;
}
旋转有序数组的二分查找 http://www.cnblogs.com/grandyang/p/4325648.html
无重复数字:int search(vector<int>gt;& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) /
2;
if (nums[mid] == target) return
mid;
else if (nums[mid] <
nums[right]) {
if (nums[mid] < target
&& nums[right] >= target) left = mid + 1;
else right = mid - 1;
} else {
if (nums[left] <= target
&& nums[mid] > target) right = mid - 1;
else left = mid + 1;
}
}
return -1;
}
有重复数字:http://www.cnblogs.com/grandyang/p/4325840.html
bool search(int A[], int n, int target) {
if (n == 0)
return false;
int left = 0,
right = n - 1;
while (left
<= right) {
int mid =
(left + right) / 2;
if (A[mid]
== target) return true;
else if
(A[mid] < A[right]) {
if
(A[mid] < target && A[right] >= target) left = mid + 1;
else
right = mid - 1;
} else if
(A[mid] > A[right]){
if
(A[left] <= target && A[mid] > target) right = mid - 1;
else
left = mid + 1;
} else
--right;
}
return false;
}
删除数组中的重复元素
有序数组中去除重复项 http://www.cnblogs.com/grandyang/p/4329128.html
int
removeDuplicates(vector<int>& nums) {
if (nums.empty()) return 0;
int j = 0, n = nums.size();
for (int i = 0; i < n; ++i) {
if (nums[i] != nums[j]) nums[++j] =
nums[i];
}
return j + 1;
}
实现一个计算器计算简单的表达式字符串
+-: http://www.cnblogs.com/grandyang/p/4570699.html
+-*/: http://www.cnblogs.com/grandyang/p/4601208.html
+-*/(): http://www.cnblogs.com/grandyang/p/8873471.html
memcopy和memove的区别?memcopy和memove的实现?
https://blog.csdn.net/li_ning_/article/details/51418400
都是拷贝一定长度的内存的内容,区别是当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。
memcpy函数的实现
void *memcpy(void *dest, const
void *src, size_t count) {
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
给定一个二叉树,节点值为0-9,从根节点到叶子结点组成一个数,求二叉树所有组成的数的和
https://blog.csdn.net/i_am_bird/article/details/78173454
Rand()的范围是多少,要是生成大于范围的的随机数怎么实现
srand(time(0)); rand(); 0~32767
写一个二叉树翻转,然后写个测试(为了写这个测试我还白送一个二叉树层次遍历emmm)
https://blog.csdn.net/qq_29762941/article/details/80909342
测试:反转两次,再和原来的二叉树比较是否相同
手写堆排序,然后分析下建堆时间复杂度(从n/2开始向上建堆的话是O(n))
https://blog.csdn.net/yuzhihui_no1/article/details/44258297
strcpy安全性,如何实现安全,strnpy,写一下并测试,
https://blog.csdn.net/ZH___xin/article/details/51985562
写sql语句(A表存储有每个电话号码当月通话记录,表B是电话号码集合,求表B每个号码通话次数),大概就是比较简单的连表查询,加count
select B.telno, count(B.telno)
from A right join B
where A.telno = B.telno
group by B.telno
假设上面题中A B两个表存在文件,怎么编程统计? 我答的使用hashmap存储电话和次数,时间复杂度呢?
只需要扫描两个文件各一遍O(n+m)
两字符串最长公共子串, 最长公共子序列
https://blog.csdn.net/u012426298/article/details/82796660
打印二叉树每层最右边的节点 层序遍历 LeetCode 199
http://www.cnblogs.com/grandyang/p/4392254.html
手写代码 回形矩阵
顺时针回形打印矩阵的元素LeetCode 54
http://www.cnblogs.com/grandyang/p/4362675.html
判断在一个矩阵中是否存在一条包含某字符串所有字符的路径
https://blog.csdn.net/qq_21997625/article/details/84640353
3sum 数组中三数之和为0的所有三元组 leetcode 15
微信的附近的人这个功能,如果让你实现,你准备怎么做,
地理位置网格分块,存块ID,然后四叉搜索。你的经纬度换算成网格ID,同网格的人撸出来,临近网格的人撸出来,搞定。把地理位置分块,怎么把经纬度转化成网格 ID 呢。本质上就是hash
客户端固定时间发送经纬度(x,y)到服务器s,服务器存储每个登陆的用户的经纬度到表t中,表t按照经纬度分表,将地图分成一个个的小格子。当用户点击“附近的人”时,对用户(x,y)进行计算,最多一次查询其中的4个格子(子表),计算两点间距离获取结果(有点像桶排序)。性能上可以将表t替换为内存结构,容灾即可。
从实际的微信提供的功能来看,附近的人并不太多,估计是其对地图划分的格子很小。
MongoDB的LBS功能实现附近的人
https://www.nowcoder.com/discuss/165952?type=0&order=0&pos=414&page=1
微信小程序团队一共有 n 名成员,决定出去秋游,在海边遇到出租摩托艇的杰克马,马先生手上有 m
辆待出租的摩托艇,价格分别是 b1 、b2 ... bm;
由于习惯了微信支付,团队中每个人身上的现金都有限,分别是 a1 a2 ... an,对了,一起出门的老板还带有 S 元的团队经费,这个经费是每个人都可以使用的
那么考虑以下两个场景
场景1
团队成员都很有爱,都愿意借钱给其他同事,那么这时候团队最多能租到多少摩托艇
//贪心法;把所有的钱收集起来,按摩托艇的价格从低到高租借摩托艇
int
isAll(int a[n], int b[m], int
S){
int sum=0;
for(int i=0;i<n
;++i)
sum+=a[i];
sum+=S;
sort(a,a+n);
int
i
= 0;
while
(sum
- m[i] > 0) {
sum
-= m[i];
i++;
}
return
i;
}
场景2
团队成员都十分小气,是不愿意借钱给别人的,那么请考虑以下两个问题
//问题一 老板是否能想到一个策略,使得所有人都能租到摩托艇?
//贪心法;钱少的人租借便宜的摩托艇,补贴
public
static boolean isAll(int[] n, int[] m, int S){
if
(n.length > m.length) { return false; }
Arrays.sort(n);
Arrays.sort(m);
for
(int i=0; i<n.length; i++) {
int
need = n[i] - m[i];
if
(need < 0)
S
+= need;
}
return
S >= 0;
}
//问题二 请问给出一个策略
// - 使得整个团队租到最多的摩托艇
// - 在租到最多摩托艇的情况下,整体的支出尽量的少
//二分法+贪心
private static int n[];
private
static int m[];
private
static int S;
public
static int[] isAll(int[] n, int[] m, int S){
Arrays.sort(n);
Arrays.sort(m);
Main.n
= n; Main.m = m; Main.S = S;
int
l =0, r = m.length; //摩托艇的数量
while
(l < r)
{
int
mid = l + r + 1 >> 1;
if
(can(mid)) { l = mid; }
else
{ r = mid - 1; }
}
int
ans = 0;
for
(int i=0; i<l; i++) {
ans
+= m[i];
}
return
new int[] {l, ans};
}
private
static boolean can(int count) {
int
tmpS = S;
for
(int i = count-1,j = n.length-1; i>=0; i--, j--) {//让最多钱的人买最贵的摩托艇
if
(n[j] < m[i]) {
tmpS
-= (m[i] - n[j]);
}
if
(tmpS < 0) { return false; }
}
return
true;
}
判断一个字符串是不是两个有序的字符串交错组成的。 Leetcode
97
编程题:递增数组中找两个数和为某个固定值。设计测试用例 Leetcode 1
给你一个数组和数组元素的个数,求平均值。
int avg(int x, int y)
{
return (x & y) + ((x ^ y) >> 1);
}
两个非常大的数相加 Leetcode 415
c++后台开发面试常见知识点总结(六)算法手写的更多相关文章
- c++后台开发面试常见知识点总结(一)c++基础
指针和引用的区别 extern,const,static,volatile关键字 #define 和const的区别 关于typedef和#define; C++程序中内存使用情况分析(堆和栈的区别) ...
- c++后台开发面试常见知识点总结(二)网络编程
(1)TCP和UDP有什么区别? TCP是传输控制协议,提供的是面向连接的,可靠地字节流服务.使用三次握手建立连接,四次挥手释放连接.UDP是用户数据报协议,传输的是UDP数据报,是无连接的,而且没有 ...
- c++后台开发面试常见知识点总结(五)场景设计
搜索引擎的实现,会用到哪些重要的数据结构 设计实现一个HTTP代理服务器 / web服务器 / FTP服务器/ 设计实现cache缓存web服务器的网页访问记录 把一个文件快速下发到100w个服务器 ...
- c++后台开发面试常见知识点总结(四)数据库
数据库的索引类型 聚集索引和非聚集索引的区别(叶节点存储内容) 唯一性索引和主码索引的区别 索引的优缺点,什么时候使用索引,什么时候不能使用索引(重点) 索引最左前缀问题 数据库中事务的ACID 数据 ...
- c++后台开发面试常见知识点总结(三)操作系统
静态链接库和动态链接库的区别 一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止 Debug和Release的区别 临界区互斥量信号量事件进程互斥与同步 进程有哪几种状态,状态转换图, ...
- 面试总结:鹅厂Linux后台开发面试笔试C++知识点参考笔记
文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 文章是由自己笔试面试腾讯的笔记整理而来,整理的时候又回顾了一遍,中间工 ...
- Linux后台开发面试问题汇总
个人从事安全后台开发,当然是linux环境下的了.举几个常见的问题.1. 数据结构基础.比如实现一个最简单的哈希表.2. 操作系统基础.linux进程模型,堆/栈的区别,大概的位置,各往哪个方向生长, ...
- 拼多多后台开发面试真题:如何用Redis统计独立用户访问量
众所周至,拼多多的待遇也是高的可怕,在挖人方面也是不遗余力,对于一些工作3年的开发,稍微优秀一点的,都给到30K的Offer,当然,拼多多加班也是出名的,一周上6天班是常态,每天工作时间基本都是超过1 ...
- Java面试常见知识点总结(三)
21.volatile关键字: 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: (1) 保证了不同线程对这个变量进行操作时的可见性,即一个线程 ...
随机推荐
- BZOJ3622 已经没有什么好害怕的了 二项式反演+DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3622 题解 首先显然如果 \(n - k\) 为奇数那么就是无解.否则的话,"糖果& ...
- 详解如何定义SQL Server外关键字约束
SQL Server外关键字约束定义了表之间的关系.当一个表中的一个列或多个列的组合和其它表中的主关键字定义相同时,就可以将这些列或列的组合定义为外关键字,并设定它适合哪个表中哪些列相关联.这样,当在 ...
- kafka-server.properties
# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreement ...
- myeclipse svn重新定位 本地文件 svn 重新定位
我们在用工具myeclipse开发项目时,当资源库存储空间不够时,我们就需要添加资源库,涉及到我们切换项目资源库,下面就介绍一下svn资源库重新定位步骤 1,window到show view到othe ...
- html 和 body标签的 css 设置
个人猜测浏览器的机制:H5页面底板上有一张画布,画布高度可以被撑高.html.body等元素是固定在画布上的.浏览器中页面的滚动是跟着画布滚动的.(fixed定位是脱离这种机制的,相对浏览器窗口定位的 ...
- How to show out three rows from the same databand On A4?
How to show out three rows from the same databand On A4? Quote Post by DoraHuang » Tue Mar 13, 2018 ...
- python3项目打包成exe可执行程序
使用pyinstaller将python文件打包成exe程序,打包步骤如下: 一.安装pyinstaller (1)win+R输入cmd,打开命令窗口 (2)安装pyinstaller,安装指令:pi ...
- Python笔记(三)_字典与集合
字典dict 映射类型,以键-值的方式存储,通过键来取相应的值 member={'one':1,'two':2,'three':3} 创建字典member=dict('苹果'='apple','桔子' ...
- trizip haskell implementation
1 trizip :: [a] -> [b] -> [c] -> [(a,b,c)] 2 trizip a b c 3 | null a = [] 4 | null b = [] 5 ...
- Python 中类和实例的通俗讲解
本文为转载整理,我转过来作为备份留作自己查看,请点击链接阅读原文.原文链接为:点此 Python类与实例的讲解,相当通俗易懂.非常推荐! class Person: 注意,类的名称一般用大写字母开头, ...