每日算法之1

每日算法之1

1.之输出数组中重复出现的数字

//问题描述:给出n个长度的数组,其中含有随机数,输出其中重复出现的数字,并计算其出现的次数

/*
算法分析:数据结构,n个随机数的数组,含int重复数字,int次数的结构体数组
        过程分析,首先进行一次快排,然后对数组进行遍历扫描,每次判断当前元素与下一个元素是否相等
        如果相等,则存入该数,并进行计数,直到不相等,存入计数值;重置,开始下一次扫描
        直到与最后一个数判断完毕;;将该数组输出
*/

//算法实现:
void quickSort(int a[],int l,int r){
    int temp;
    int i=l,j=r;
    if(l<r){
        temp=a[l];
        while(i<j){
            //反向扫描
            while(a[j]>=temp && i<j) --j;
            if(i<j) a[i++]=a[j];
            //正向扫描
            while(a[i]<=temp && i<j) ++i;
            if(i<j) a[j--]=a[i];
        }
        a[i]=temp;//i、j重合退出循环,将中轴值填上,并拿到新的中轴位置
        
        quickSort(a,l,i-1);
        quickSort(a,i+1,r);        
    }
}
void generateRandom(int a[],int n,int Max){//定义一个随机数生成函数
    srand((unsigned)time(NULL));
    for(int i=0;i<n;++i){
        a[i]=rand()%MAX;
    }
}
struct repeatNum_s{
    int reNum;
    int reCount;
};
void findRepeatNum(int a[],int n){
    if(n<2 || a==NULL) cout<<"error";
    
    repeatNum_s res[n];//自定义一个存入重复数字的数组
    int count;
    int i=0;
    int j=0;
    
    while(i<n-1){//注意边界条件为0~n-2
        if(a[i]==a[i+1]){
            count=1;
            while(a[i]==a[i+1] && i<n-1){
                ++count;
                ++i;
            }
           res[j].reNum=a[i];
           res[j].reCount=count;
           ++j; 
        }
        ++i;
    }
    if(j==0) cout<<"没有重复数字!"<<endl;
    for(int k=0;k<j;++k)
       cout<<"重复的数字为:"<<res[k].reNum<<" 重复次数为:"<<res[k].reCount<<"\n";
}
//时间复杂度分析:快排时间复杂度为O(nlogn)+查找时间复杂度为:O(n),所以最终为O(n)
//,空间复杂度为O(n)

//测试用例:
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib> 
using namespace std;
int main(){
	int MAX=1000;
	int a[MAX];
	
	generateRandom(a,1000,MAX);
	quickSort(a,0,MAX-1);
	
	for(int i=0;i<MAX;++i)
		cout<<a[i]<<"\t";
	cout<<endl;
	
	findRepeatNum(a,1000);
	
}

2.之查找行列非递减二维数组指定元素

//问题描述:给定一个二维数组,其行,列元素非递增排列,要求查找指定元素k是否存在?

/*
	算法分析:从右往左扫描,如果该值大于k,则将列减一剔除;如果相等,则返回true,退出;如果小于
			则行加一剔除;如此循环直到最后一行,第一列
*/

//算法实现:
void find(const int *matrix,int rows,int columns,int k){//使用二维数组行和列传参的形式!!
    int row=0;
	int col=columns-1;
    if(matrix!=NULL && rows>0 && columns>0){//注意此法不使用new创建的二维数组,由于不连续!
        while(row<rows && col>=0){
            if(matrix[row*columns+col]==k){
				cout<<"元素k="<<k<<"所在行:"<<row+1<<"  所在列:"<<col+1<<endl;
				
				for(int i=row+1;i<rows;++i){//需要判断是否该列含有多个相等值 
					if(matrix[i*columns+col]==k)
						cout<<"元素k="<<k<<"所在行:"<<i+1<<"  所在列:"<<col+1<<endl;
                    else break;
				}
				--col;//判断完毕才将此列剔除 
            }
            else if(matrix[row*columns+col]>k){
				--col;
            }
            else {
                ++row;
            }
        }
    }else
    	cout<<"not found!!\n";
}
//复杂度:最坏情况下时间复杂度为O(col || row),线性时间

int main(){
	//测试用例
	int a[][4]={{2,2,2,2},{2,2,2,2},{2,2,2,2},{2,2,2,2}};
	find((int*)a,4,4,2); //注意二维数组传入数组指针
} 

3.之C++字符串

//1、C++规定字符串一般结尾都会自动添加一个结束标志:‘\0’,所以常量字符串的长度一般需要+1

//2、C++一般将常量字符串单独放于一个内存区域

#include <iostream>
using namespace std;
int main()
{
    /*3、当一个字符串常量出现于表达式中时,它的值是个指向第一个字符的指针常量。编译器把这个指定字符的一份copy存储在内存的某个位置,
    并存储一个指向第一个字符的指针。*/		
    cout << *"xyz" << endl;//x
    cout << *"xyz"+1 << endl;//y的ascll码
    cout << "xyz"[2] << endl;//z
    //cout << *("xyz"+4) << endl;
    cout << "xyz"+1<< endl;//yz

    /*======等价于======*/
    cout << "/*======等价于======*/"<< endl;

    const char *p="xyz";//由于是常量字符串,必须使用一个指针常量进行接受,否则会出现警告
    
    cout << *p << endl;//x
    cout << *p+1 << endl;//y的ascll码
    cout << char(*p+1) << endl;//y
    cout << p[2] << endl;//z
    cout << p+1<< endl;//yz
    	
    return 0;
}

//原因在于:C++对cout<<输出字符串数组时对运算符进行了重载,输出时直到'\0'字符为止;;

//4、所以如果是常量字符串,或者指向字符串常量的指针,或者string类型的,输出时都会直接输出整个字符串;
//这一点与整型数组是不同的

//5、对于相同的字符串常量,它的内存地址是相同的,一般都会存于静态全局data区域
//如:p1和p2指向相同的内存地址
char *p1="hello world";
char *p2="hello world";

//既然常量字符串实际是一个地址,所以定义一个字符数组时可以直接赋值初始化,但是非定义时不能够进行直接
//将一个常量字符串赋给一个数组,类型都不一致,此外

//千万记住常量字符串实际是一个常量,意味着无法通过指针修改常量值
const char *p="hello world!";

*p="yang";//试图修改而出错


4.之字符串替换空格

//问题描述:输入一个字符串数组"we are happy.",要求将其中的空格进行替换为%20

/*
	算法分析:思路一:正向扫描整个字符串,遇到空格,则将其后的字符串后移2个字符,并将空格替换为%20;
					直到遇到结束字符'\0';; 缺点,虽然不需要借助辅助空间,但是时间复杂度为O(n^2)
			思路二:先正向扫描一遍,统计所有空格的数量,算好新字符串的长度,使用两个指针p1,p2
				指向原来的字符串和新的字符串末尾,移动p1指针并将字符复制在p2处,碰到空格,
				则直接赋值%20;直到两个指针相等
				优点:时间复杂度为O(n)线性的时间
*/

//算法实现:
void replace_space(char c[]){
    if(c==NULL){
        cout<<"error!"<<endl;
        return;
    }
    int spaceNum=0;
    int newLength;
    int oldLength;
    int i;
    for(i=0;c[i]!='\0';++i){
        if(c[i]==' ')
            ++spaceNum;
    }
    oldLength=i+1;
    newLength=spaceNum*2+oldLength;
    
    char *p1=&c[oldLength-1];
    char *p2=&c[newLength-1];
    while(p1!=p2){
        while(*p1!=' ' && p1!=p2){
            *p2=*p1;
            --p1;
            --p2;
        }
		*p2='0';--p2;
        *p2='2';--p2;
        *p2='%';--p2;
        --p1;
    }
    cout<<c;
}

/*
!!注意:数组名a和&a,及数组指针和指针数组的区别
	假设:	
	定义一个数组名int a[100];
	a等价于int*,表示指向数组首元素的地址的一个指针;;&a的类型则相当于int**,是所谓指向整个数组的指针,是数组元素类型的二级指针
	注意:&a 和a 的值一样,但代表的意义不同
	
	a + 1是相当于a + 1 * sizeof(int)
	&a + 1 * sizeof(a)的,所以会偏移一个数组长度
	
	数组指针和指针数组的区别:
	int* p1[10];//表示指针数组
	int (*p1)[10];//表示数组指针
	
	int **p1=new int*[10];//表示二级指针
	首先一级指针初始化是地址赋值,但是二级指针赋值是使用指针赋值而非地址
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值