《剑指offer》每日分享三道题- 2 day

本文介绍了《剑指Offer》中三种找出数组中出现次数超过一半数字的方法,包括unordered_map统计、排序验证和候选法。同时讲解了如何用递归实现单链表的逆序打印,并探讨了字符串空格替换为%20的实现。这些题目涵盖了数据结构和算法的基础应用。
摘要由CSDN通过智能技术生成

《剑指offer》系列第二弹,让我们用饱满的热情,迎接接下来的几道小题。 >本系列分享的都是常规做法和全新思路的总结,各位可千万不要看着眼熟,而错过新颖的思路噻!!!

1.将数组中出现次数超过一半的数字返回

(1)采用unordered_map方式

这应该是在我们学习了C++等相关知识后,最方便的一种做法。

代码和注释代表思路如下: 先找到keyi值,如果是首次出现就设置次数为1,不是第一次就++次数

#include<unordered_map>
int MoreThanHalfNum_Solution(vector<int > numbers)
{
	int half=numbers.size()/2;//先拿到一半的个数是多少
	unordered_map<int,int> map;//采用<数字,次数>的映射关系,最后统计出现的次数
	//想要统计个数就涉及到遍历
	for(int i=0;i<numbers.size();++i)
	{
		auto it=map.find(numbers[i]);//找到keyi值
		if(it==map.end())//如果没有找到,就首次进行插入
		{
			//在i的位置,次数加为1,表示第一次出现
			map.insert({numbers[i],1});
		}
		else//如果不是第一次出现,次数就++
		{
			map[numbers[i]]++;
		}
		
		if(map[numbers[i]]>half)
			return numbers[i];
	}
	return 0;
}

(2)先排序再找中间位置元素记录次数进行验证

这个方式的思路就是:

如果他的次数大于一半,那么在进行排序之后中间元素就一定是内个次数大于一半的,
然后再遍历一遍验证这个元素的个数是否大于一半。

int MoreThanHalfNum_Solution(vector<int > numbers)
{
	sort(numbers.begin(),numbers.end());
	
	int target=numbers[numbers.size()/2];
	int count=0;
	for(int i=0;i<numbers.size();++i)
	{
		if(target==numbers[i])
			count++;
		
	}
	if(count>numbers.size()/2)
		return target;
	return 0;
}

(3)候选法,两个不同的数据相消减

思路:既然出现次数大于一半,如果两个元素不相同,
那么我选择一换一的方式对于数组进行抵消,剩下的内个就是最多的内个。
具体实现:cond:就是值,cnt就是次数,通过对于众数次数的–,实现相消的效果。
遇到不同的就减减。

int MoreThanHalfNum_Solution2(vector<int> numbers)
	{
		int cond = -1;
		int cnt = 0;
		for (int i = 0; i < numbers.size(); ++i)
		{
			if (cnt == 0)
			//这个cnt就是此时众数和非众数继续相消所剩下的个数。
			//如果消减只剩下0,就说明前面的区间消除完毕,继续消减后面的
		    //反正众数就是比非众数多
			{
				cond = numbers[i];
			    ++cnt;
			}
			else//相同就++,不同就--,基础就是众数的存在,在两两相消的进程中,总会剩下一个。
			{
				if (cond == numbers[i])
					++cnt;
			    else
				--cnt;
			}
		}
		//得到cond数字,然后进行数出现的次数
		cnt = 0;
		for (const int k : numbers)
		{
			if (cond == k)
				++cnt;
		}
		if (cnt > numbers.size() / 2)
			return cond;

		return 0;
	}

2. 将字符串中的空格替换成 %20

一个空格是一个字符,替换成的这个是三个字符。(因题而异),那么我们想的就是当遇到空格的时候就进行替换,就涉及到扩容的问题,扩几个的问题。

指针示意图如下:
在这里插入图片描述

void replaceSpace(char* str,int length)
{
	int count=0;
	char* start=str;
	//记录,空格的次数,便于扩充之后新的尾指针的确定
	while(*start)
	{
		if(isspace(*start))//如果是空格,就记录空格的次数
		{
			count++;
		}
		start++;
	}
	
	char *old_end =str+length;
	char* new_end=str+length+2*count;
	while(old_end>=str&&new_end>=str)
	{
		if(isspace(*old_end))
		{
			*new_end=*old_end;
			//将不是空格的字符向后移动,以便给插入字符留出空间
			new_end--,old_end--;
		}
		else
		{
			//先赋值,再往前移动位置
			*new_end--='0';
			*new_end--='2';
			*new_end--='%';
			old_end--;
		}
	}
}

3.递归的思路实现单链表的逆序打印

递归的方式实现 递归返回的时候实现打印或者内容的保存
不理解的bro 可以画个图理解一下

void Fprint(ListNode listnode, ArrayList<Integer>list)
{
	if(listNode==NULL)
		return ;
	Fprint(listnode .next,list);
	list.add(listnode.val);
}
ArrayList<Integer>print(ListNode listnode)
{
	ArrayList<Integer> list=new ArrayList<>();
	Fprint(listnode,list);
	return list;
}

手绘图如下:
在这里插入图片描述

4. 大郎,喝鸡汤了!!!

人生的精彩,就在于接下来的每一个场景都有他的未知性。或许在某一个瞬间,或许某一个场景,遇到的某一个人发生的某一个事都会给你心灵上的安慰。如春风般沐浴,如夏雨般滋润我们的心田。
让我们热爱生活,认真走好每一步。诗意般的远方就会越来越近。

Fighting!my bro!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值