sizeof求字符串长度时包含"\0"
正数的补码是他本身,负数的补码是其相应正数取反码加1。
假设有一个 int 类型的数,值为5,那么,我们知道它在计算机中表示为:
00000000 00000000 00000000 00000101
5转换成二制是101,不过int类型的数占用4字节(32位),所以前面填了一堆0。
比如:00000000 00000000 00000000 00000101 的反码是:11111111 11111111 11111111 11111010。
那么,补码为:
11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
所以,-5 在计算机中表达为:11111111 11111111 11111111 11111011。转换为十六进制:0xFFFFFFFB。
有36辆自动赛车和6条跑道,没有计时器的前提下,最少用几次比赛可以筛选出最快的三辆赛车?
36车分6组,每次取前三,并标记顺序,决出18辆车,18分3组,6组的第一名是一组,第二名是一组,第三名是一组。第一名这组先比赛,可以决出前3,然后将前三的第一名出列,现在只差第二名和第三名,从第一名其相应队伍中拿出后两名,再从第二名队伍中拿出他的第二名。第三名队伍中的所有剩下的车都没有希望。(第二名和第三名只会从这五个车中产生),这样取前两名就得到所求。总共需要6+1+1=8次
一个系统,提供多个http协议的接口,返回的结果Y有json格式和jsonp格式。Json的格式为{"code":100,"msg":"aaa"},
为了保证该协议变更之后更好的应用到多个接口(工厂方法:根据请求的不同,调用不同的方法,返回不同的类型对象),为了保证修改协议不影响到原先逻辑的代码(适配器),以下哪些设计模式是需要的?协议的变更指的是日后可能返回xml格式,或者是根据需求统一对返回的消息进行过滤(装饰者:是用来动态添加功能的,就是过滤 消息,比如非法字符&&&之类的,消息过长之类 )。
适合并行处理的排序算法是() 基数排序
并行处理也就是将大的数据分块,每个执行流处理一块,然后合并,之后再分块,基数排序可以做到这样
枚举排序,通常也被叫做秩排序,算法基本思想是:对每一个要排序的元素,统计小于它的所有元素的个数,从而得到该元素在整个序列中的位置,时间复杂度为O(n^2)
下述二叉树中,哪一种满足性质:从任一结点出发到根的路径上所经过的结点序列按其关键字有序()
一:二叉排序树的左子树节点值都小于根节点值,右子树节点值都大于根节点,因此假如根节点值为10,其左节点值为5,其左节点的右节点值为8,那么从右节点到跟节点的值依次为8 5 10,显然不是有序的
二:哈夫曼树是带权路径最小的二叉树,也不是
三:AVL树是二叉排序树,只不过其左右子树的高度差有限制,在1之内,由一只非有序
四:堆是一种完全二叉树,其有大顶堆和小顶堆的分别,大顶堆是指其每个节点的值都大于其左右孩子的值(小顶堆反之),因此从任一节点到根节点是升序排列的(小顶堆反之)
非线性结构是指在该类结构中至少存在一个数据元素,它具有两个或者两个以上的前驱或后继.如树和二叉树等.
做题目时,注意初始化局部变量,修改字符串后,字符串结尾符要写上。
注意循环条件的判断。这个容易错。
在用二分法求某一个数第一次出现的时候,一定要注意我们做判断的时候数组的越界。因为我们这里有对mid进行改变,所以有必要对其进行合法性的再次判断。
if(arr[mid]==k){
if((mid-1>=0&&arr[mid-1]!=k)||mid-1==0)
return mid;
else
end = mid-1;
}
这个采用递归,首先判断子树的平衡性由子树的深度得出这个树是否是平衡的。
要做到先子树后本树,我们必须加一个参数用于保存树的深度,因为当两个子树都是平衡的,然后在判断本树是否平衡的时候,我们需要两个子树的深度来判断。因为我们要把深度传给调用者,所以得采用传指针的方式。失误的地方:if后面没有{}导致return永远执行。注意这里是递归调用,在局部变量中申请两个变量用于存储返回值。
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
int depth = 0;
return IsBalanced(pRoot,&depth);
}
bool IsBalanced(TreeNode*proot,int *depth){
if(proot==NULL){
*depth=0;
return true;
}
int left = 0,right = 0;
if(IsBalanced(proot->left,&left)&&IsBalanced(proot->right,&right)){
if((right-left<=1)&&(right-left>=-1)){//注意这里
*depth = left>right?(left+1):(right+1);
return true;
}<span style="font-family: Arial, Helvetica, sans-serif;">//注意这里</span>
}
return false;
}
};
数组中只出现一次的数字,注意问题*num1和*num2的初始化,还有忘记了提前返回的return和默认的错误输出是什么。树上的做法是,当输入不符合要求时,直接返回,并没有对输入做修改。
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
<span style="white-space:pre"> </span>int result = 0;
*num1=0;
*num2=0;
if(data.size()>1){
vector<int>::iterator data_begin = data.begin();
while(data_begin!=data.end()){
result^=*data_begin;
data_begin++;
}
int n = GetFirstBit(result);
data_begin = data.begin();
while(data_begin!=data.end()){
if(IsBit1(*data_begin,n)){
*num1=*num1^*data_begin;
}else{
*num2=*num2^*data_begin;
}
data_begin++;
}
return;//这里忘记了
}
*num1=0;//默认错误输出
*num2=0;//<span style="font-family: Arial, Helvetica, sans-serif;">默认错误输出</span>
return;
}
int GetFirstBit(int num){
int n = 0;
while((num & (0x1<<n++))==0){
}
return n-1;
}
bool IsBit1(int num,int n){
num=num>>n;
if(num&0x1){
return true;
}
return false;
}
};
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。 注意:每一种情况都要有return;
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> &array,int sum) {
vector<int> result;
int length = array.size();
if(length < 2){
return result;
}
int start = 0;
int end = length -1;
while(start<end){
int cursum = array[start]+array[end];
if(cursum==sum){
result.push_back(array[start]);
result.push_back(array[end]);
return result;
}else if(cursum>sum){
end--;
}else{
start++;
}
}
return result;//刚开始忘了,老是导致溢出,这个已经犯了好几次类似错误了。
}
};
和为S的所有正整数序列:
因为我们要得到下标区间,所以不必对区间进行重复计算,所以我们让区间单向增加。大循环主要是增加big,在一定条件下增加small。然后small的操作又是在一个循环中。每次修改边界时都需要做判断,以决定是否还执行循环。
我们每次得到的结果是一个区间,所以要统计这个区间的值,所以得有两个下标,然后我们还得有一个用于控制循环的终止的下标。因为控制循环终止的下表是一直增加的。这里与以前编程所不同的就是,我们并不是每次都修改用于循环终止下标。不同于上面的是,我们这里不对big进行减操作。在寻找所要求结果的时候,我们是一直操作两个下标。只对他们进行++操作。也就是一直对这两个下标做曾
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> >result;
if(sum < 3){
return result;
}
int small,big,middle,cursum = 0;
small = 1;//初始化为1
big = 2;
middle = (sum+1)/2;//
cursum = small+big;
while(small < middle){//每次操作是都要判断是否满足输出要求
if(cursum == sum){//相等的操作对应的是这个
vector<int> temp;
gather_result(temp,small,big);
result.push_back(temp);
}
while(cursum > sum && small < middle){//内嵌循环,这个很重要。当太大时对应的操作是这个
cursum-= small;//并不是每次都对small进行操作,这个是和以往不同的地方。
small++;//只有++操作
if(cursum == sum){
vector<int> temp;
gather_result(temp,small,big);
result.push_back(temp);
}
}
big++;//只有++操作,前面两个执行完以后对应的肯定是小于了,所以我们执行crusum增操作。
cursum+=big;
}
return result;//又是忘记了return,导致超时
}
void gather_result(vector<int>&result,int small,int big){
while(small<=big){
result.push_back(small);
small++;//少用while,因为自己老是忘记对条件进行自增运算,忘记这个,导致内存不够
}
}
};
翻转单词顺序列:
需要考虑的是当句子中没有空格时,还有最后一个单词组。当句子中没有空格时不用进行处理。当是最后一个单词组时,和普通的单词组不一样。
class Solution {
public:
string ReverseSentence(string str) {
if(str.size()<1){
return str;
}
bool changed = false;
int begin = 0;
int end = 0;
int length = str.size();
while(end<length-1){
while(begin<length-1&&str[begin]==' '){
begin++;
}
end=begin+1;
while(end<length-1&&str[end]!=' '){
end++;
}
if(end<length-1&&str[end]==' '){
swap_str(str,begin,end-1);
changed = true;
begin = end++;
}
}
if(end==length-1&&str[begin]!=' '){//最后一个单词组
if(changed)
swap_str(str,begin,end);
}
if(changed){//如果只有一个单词
swap_str(str,0,str.size()-1);
}
return str;
}
void swap_str(string&str,int begin,int end){
while(begin < end){
char temp = str[begin];
str[begin]= str[end];
str[end]=temp;
begin++;
end--;
}
}
};
关于链表:我们要考虑这个是否是头结点。头结点的处理和普通节点的处理不一样。还有尾节点。
写递归的时候一定要注意返回条件要先写。
注意处理时我们的循环条件的变动。更新条件变量等关键变量。
注意链表修改可能涉及到头结点,所以我们的参数是二级指针。注意也要修改这个指针。
归并排序不同于其他两种高级排序的地方是:他是一种稳定的排序方法。
归并排序的一种实现:之所以要写出这个代码,主要是因为其少了好多次拷贝。刚开始时,我们让dst和src数据一样,当最后返回时,dst为排好序的数组,src还差一次归并就有序。这里的窍门就是每次递归时都交换data和copy。这样就少了那种传统方法的copy到data的拷贝,但是最终的结果是在copy数组中,所以dst为有序数组。
<pre name="code" class="cpp">void mergesort(int * data,int *copy,int start,int end)
{
if(start==end){
copy[start]=data[start];
return;//注意递归调用的return。
}
int length = (end-start)/2;
mergesort(copy,data,start,start+length);
mergesort(copy,data,start+length+1,end);
int i = start+length;
int j = end;
int indexCopy = end;
while(i>=start&&j>=start+length+1){
if(data[i]>data[j])
copy[indexCopy--]=data[i--];
else
copy[indexCopy--]=data[j--];
}
for(;i>=start;--i)
copy[indexCopy--]=data[i];
for(;j>=start+length+1;j--)
copy[indexCopy--]=data[j];
return ;
}
int main(){
int src[100];
int dst[100];
int i=0;
while(i<100){
dst[i]=src[i]= rand()%200;
cout << src[i]<< "\t";
i++;
}
cout << endl;
mergesort(src,dst,0,99);
i=0;
while(i<100){
cout << dst[i]<< "\t";
i++;
}
cout << endl;
}
if((middleIndex<length-1&&data[middleIndex+1]!=k)||(middleIndex == length-1))
这种在内部对变量做加减操作的一定要先判断是否越界。
判断二叉树是否是平衡的:
先判断子树,再通过子树的结果判断根节点是否平衡。
因为既要判断是否平衡,又要保存子树的深度,所以我们的函数返回值是bool,参数是int&。我们是通过返回值判断读不读传进去的实参的。
注意我们要分别对左右子树调用IsBalanced函数,所以我要定义两个整数,用于左右子树调用。之后如果都满足平衡,我们还要在这个根节点出进行平衡的判断,当两个整数参数的绝对值之差小于等于1时,才满足平衡条件,更新深度为两者最大值加一,并返回true。