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) 保证了不同线程对这个变量进行操作时的可见性,即一个线程 ...
随机推荐
- bzoj3717 [PA2014]Pakowanie 贪心+状压DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3717 题解 这道题大概也就只能算常规的状压 DP 吧,但是这个状态和转移的设计还是不是很好想. ...
- BZOJ3038 上帝造题的七分钟
Time Limit: 3 Sec Memory Limit: 128 MB Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. "第一分钟,X说, ...
- 每天一个linux命令:which(17)
which which命令用于查找并显示给定命令的绝对路径,环境变量PATH中保存了查找命令时需要遍历的目录.which指令会在环境变量$PATH设置的目录里查找符合条件的文件.也就是说,使用whic ...
- Java并发与多线程与锁优化
前言 目前CPU的运算速度已经达到了百亿次每秒,所以为了提高生产率和高效地完成任务,基本上都采用多线程和并发的运作方式. 并发(Concurrency):是指在某个时间段内,多任务交替处理的能力.CP ...
- 【HDU5306】【DTOJ2481】Gorgeous Sequence【线段树】
题目大意:给你一个序列a,你有三个操作,0: x y t将a[x,y]和t取min:1:x y求a[x,y]的最大值:2:x y求a[x,y]的sum 题解:首先很明显就是线段树裸题,那么考虑如何维护 ...
- [CSP-S模拟测试86]题解
好久没有写整套题的题解了呢……主要是这两天考试题愈发神仙 实在是超出了垃圾博主的能力范围啊QAQ A.异或 不难想到,如果我们得到了$[L,R]$中每一位上0和1的个数,那么答案即为$2 \times ...
- 结构体和typedef
在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{ 结构体所包含的变量或数组}; 结构体是一种集合,它里面包含了多个变量或数组,它 ...
- MATLAB 中几个颜色空间的坐标范围
在一些图象处理的程序中,我们经常要在不同的颜色空间操作,而且经常要把各颜色空间的坐标转化到 [0,1] 之间,这就需要知道一些常用颜色空间的坐标范围. 虽然可以通过颜色空间转化的公式推导这些范围,但是 ...
- Nuget-Doc:NuGet 介绍
ylbtech-Nuget-Doc:NuGet 介绍 NuGet 是适用于 .NET 的包管理器. 它使开发人员能够创建.共享和使用有用的 .NET 库. NuGet 客户端工具可生成这些库并将其作为 ...
- 信息安全-攻击-XSRF:XSRF/CSRF 攻击
ylbtech-信息安全-攻击-XSRF:XSRF/CSRF 攻击 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Ses ...