思路:遍历一遍,记录最小值和最小值的位置
bool solve(SqList &L,Elemtype &value)
{
if(L.length==0)
{
return false;//返回值为0表示出现错误。
}
int pos;
value = L.data[0];
for(int i=0;i<L.length;i++)
{
if(value > L.data[i])
{
value = L.data[i];
pos = i;
}
}
L.data[pos] =L.data[L.length-1];
L.length--;
return true;
}
思路:将两边挨个交换一下就行
void solve(SqList &L)
{
int mid = (L.length)>>1;
for(int i =0;i<mid; i++)
{
swap(L.data[i],L.data[L.length-i-1]);
}
}
思路:双指针法,一个first指针用于遍历线性表,一个second指针用于更新线性表的值,用新的表覆盖原先的表。
void solve(SqList &L,Elemtype x)
{
int first = 0, second = 0;//first用于遍历线性表,second用于存储需要的值
while(first < L.length)
{
if(L.data[first] != x)//不等于x将该值存放在L.data[second]中。
{
L.data[second] = L.data[first];
second++;
first++;
}
else
{
first ++;
}
}
L.length = second;
}
思路:用first 和second 分别表示第一个大于s和第一个小于t的数,这两个之间便是要处理的数。
bool solve(SqList &L,Elemtype s,Elemtype t)
{
int first = 0, second = L.length-1;
if(s > t || L.length ==0 )
{
return false;//返回false表示有错误
}
while(L.data[firs]<s||L.data[right]>t)//找到第一个大于s的地方存放在first第一个小于t的存放在second
{
if(L.data[first]<s )first++;
if(L.data[secodn]>t )second--;
}
if(first >= L.length || second <= 0 || first > second)//第一个大于s的在第一个小于t的数后面表示没有s-t中间的数字
{
return true;//不用处理,表示已经结束
}
while(second < L.length)
{
L.data[first]=Ldata[second];
first ++;
second ++;
}
return true //表示处理结束
}
思路与03题类似,个人觉得比王道的答案更简单。
bool solve(SqList &L,Elemtype s,Elemtype t)
{
if(s > t || L.length ==0 )
{
return false;//返回false表示有错误
}
int first = 0, second = 0;//first用于遍历线性表,second用于存储需要的值
while(first < L.length)
{
if(L.data[first] < s || L.data[first] > t )//不在s-t的范围内将其存储下来
{
L.data[second] = L.data[first];
second++;
first++;
}
else
{
first ++;
}
}
L.length = second;
return true;
}
思路双指针,判断first指向的值与second指向的值是否相等,不相等就存,相等就不存。
bool solve(SqList &L)
{
if( L.length ==0 )
{
return false;//返回false表示有错误
}
int first = 1, second = 0;//first用于遍历线性表,second用于存储需要的值
while(first < L.length)
{
if(L.data[first]!=L.data[second] )//表示不是重复的值。
{
second++;
L.data[second] = L.data[first];
first++;
}
else
{
first ++;
}
}
L.length = second + 1;
}
bool solve(SqList &L1 , SqList &L2 , SqList &ans)
{
if(L1.length + L2.length > ans.length) return false;
//合并后顺序表长度不够
int first = 0 ,second =0,third = 0;
while(first < L1.length && second < L2.length)
{
if(L1.data[first] < L2.data[second])
{
ans.data[third] = L1.data[first];
third ++;
first ++;
}
else
{
ans.data[third] = L2.data[second];
third ++;
second ++;
}
}
//将没存的残留数据存进去
if(first <L1.length)
{
while(first < L1.length)
{
ans.data[third] = L1.data[first];
third ++;
first ++;
}
}
if(second < L2.length)
{
while(second < L2.length)
{
ans.data[third] = L2.data[second];
third ++;
second ++;
}
}
return true;
}
思路:先将整个顺序表倒序,然后将前sum - m 个逆序,然后再将后面的sum - n个 逆序。
bool solve(SqList &L,int m)
{
//传参给定顺序表L 以及 m表示前面a表的个数。
for(int i = 0 ;i < (L.length>>1); i++ )//整个表倒序,将a和b的前后互换
{
swap(L.data[i],L.data[L.length - i - 1]);
}
for(int i = 0 ; i< (L.length-m)>>1 ; i++)//将倒序的b再倒为正序
{
swap(L.data[i],L.data[L.length-m-i-1]);
}
for(int i =0; i< (m)>>1 ; i++)//将倒序的a再倒为正序
{
swap(L.data[L.length-m+i],L.data[L.length-i-1]);
}
}
思路:二分查找
bool solve(SqList &L1,int x)
{
int l = 0 , r = L1.length - 1;
int mid = (l+r) >>1;//'>>'表示左移,也就是相当于除二
while (l <= r)
{
mid = (l+r) >> 1;
if( L1.data[mid] == x)
{
if(mid < L1.length-1)
{
swap(L1.data[mid],L1.data[mid + 1]);
}
//找到了就可以结束了
return true;
}
else
if(L1.data[mid] < x) l = mid +1;
else r = mid -1;
}
//二分查找得到的r表示的就是第一个比x小的数的所在的位置。
for(int i = L1.length -1 ;i >r;i--)L1.data[i+1] = L1.data[i];
L1.data[r+1] = x;
L1.length++;
return false;
}
①思路:就是和第八题几乎一模一样,a 和 b 的交换就相当于将整个数组左移了a的个数个位置,与本题的要求是一样的。
②代码
bool solve(SqList &L,int p)
{
//传参给定顺序表L 以及 m表示前面a表的个数。
for(int i = 0 ;i < (L.length>>1); i++ )//整个表倒序,将a和b的前后互换
{
swap(L.data[i],L.data[L.length - i - 1]);
}
for(int i = 0 ; i< (L.length-p)>>1 ; i++)//将倒序的b再倒为正序
{
swap(L.data[i],L.data[L.length-m-i-1]);
}
for(int i =0; i< (p)>>1 ; i++)//将倒序的a再倒为正序
{
swap(L.data[L.length-m+i],L.data[L.length-i-1]);
}
}
//分割线 其实这些操作是重复的,我们吧交换单独写一个多次调用也可以。
//---------------------------------------------------------
void reserve(SqList &L,int l , int r)
{
int m = (r-l)>>1;
for(int i =0; i<=(m) ; i++)//将倒序的a再倒为正序
{
swap(L.data[l+i],L.data[r-i]);
}
}
void converse()
{
reserve(L1,0,p-1);
reserve(L1,p,L1.length-1);
reserve(L1,0,L1.length-1);
}
例如,若序列 S1=(11,13,15,17,19),则 S1 的中位数是 15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若 S2= (2,4,6,8,20),则 S1 和 S2 的中位数是 11。现在有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和 B 的中位数。要求:
思路:双指针分别表示两个序列的下标,寻找到两个序列的中位数就行了,因为是有序的所以就是第L/2(向上取整)个数就是中位数。
//方法一:这不是最优解 , 该方法是次优解,会扣一分,15分的题扣一分问题也不大了。
int solve(SqList &L1,SqList &L2)
{
int x = (L1.length + L2.length)%2 ? (L1.length+L2.length)/2+1 : (L1.length+L2.length)/2;
//三目运算符计算中位数的位置在哪儿
int first = 0 , second = 0;
//分别代指两序列的下标
int ans = 0;
while (first + second < x)
{
if(L1.data[first] <= L2.data[second])
{
ans = L1.data[first];
first ++ ;
}
else
{
ans = L2.data[second];
second ++ ;
}
}
return ans;
}
------------------------------------------------------
//法二:王道标准答案,用的是二分查找的思维方式,时间复杂度更低自己看书吧我懒得写了。
若存在ap1=ap2=···=apm=x且m>n/2(0Sp
思路:如果到最后count大于0,那么代表k的个数要比n/2多count个
或者直接开另一个数组记录每个数字出现的次数,因为每个元素都大于0小于n;
//法一:更好想到
int solve(SqList &L1)
{
int vis[L1.length];
//因为数组是在函数里开的,所以需要初始化
for(int i=0;i<L1.length;i++)
vis[i] = 0
//遍历序列
for(int i= 0;i<L1.length;i++)
{
vis[L1.data[i]]++;
}
for(int i=0;i<L1.length;i++)
{
if(vis[i] > L1.length/2)return i;
}
return -1;
}
//时间复杂度O(n) , 空间复杂度O(n);这个答案只扣一分
----------------------------------------------
//方法二:这个是标准的答案,但是不容易想到
int solve(SqList &L1)
{
int count = 1;
int k = L1.data[0];
for(int i=1;i<L1.length;i++)
{
if(L1.data[i] == k)
{
count++;
}
else{
if(count > 0)count --;
else
{
k = L1.data[i];
count = 1;
}
}
}
if(count > 0)
{
for(int i=count=0;i<L1.length;i++)
if(L1.data[i]==k)count++;
}
if(count>L1.length/2)return k;
else return -1;
}
//时间复杂度O(n) 空间O(1);
思路:分配一个大小为n的b数组,b数组表示数字1- n出现与否,若数字i出现则b[i-1] = 1,如果刚好b数组全是1,则表示n+1是第一个为出现的正整数,否则i从0—n-1遍历,第一个b[i]==0表示第一个未出现的正整数是i+1,也说明,若0—n-1中存在未出现的值,则一定有答案在1-n中否则答案一定是n+1.
int solve(SqList &L1)
{
int *b;
b = (int *)malloc(sizeof(int)*L1.length);
memset(b,0,sizeof(b));
for(int i= 0 ;i<L1.length;i++)
{
if(L1.data[i]>0&&L1.data[i]<=L1.length)
{
b[L1.data[i]-1] = 1;
}
}
for(int i=0;i<L1.length;i++)
{
if(b[i] == 0)return i+1;
}
retur
n L1.length+1;
}
//时间复杂度O(n)空间复杂度O(n);
思路:D=|a-b| +|b-c|+|c-a| 放在平面上看其实就是最大最小值差的两倍,D = 2 *( max (a,b,c) - min(a,b,c)) 每次如果更新最大值或者第二大的值就会导致D必然变大或者不变,所以只需要更新最小的值。
int solve(SqList &L1,SqList &L2,SqList &L3)
{
int op1,op2,op3;
op1 = op2 = op3 = 0;
int ans = 2*(max(L1.data[op1],max(L2.data[op2],L3.data[op3])) - min (L1.data[op1],min(L2.data[op2],L3.data[op3])) );
while (op1 < L1.length && op2 < L2.length && op3 < L3.length && ans > 0)
{
ans = min(ans ,(2*(max(L1.data[op1],max(L2.data[op2],L3.data[op3])) - min (L1.data[op1],min(L2.data[op2],L3.data[op3])) )));
if(min(L1.data[op1],min(L2.data[op2],L3.data[op3])) == L1.data[op1]) op1 ++;
else
if(min(L1.data[op1],min(L2.data[op2],L3.data[op3])) == L2.data[op2]) op2 ++;
else
if(min(L1.data[op1],min(L2.data[op2],L3.data[op3])) == L3.data[op3]) op3 ++;
}
return ans;
}
时间复杂度O(n1+n2+n3)就是O(n) 空间复杂度为O(1);
后续会继续更新