《剑指offer》– 第一个只出现一次的字符、数组中只出现一次的数字、字符流中第一个不重复的字符、数组中重复的数字

《剑指offer》– 第一个只出现一次的字符、数组中只出现一次的数字、字符流中第一个不重复的字符、数组中重复的数字

一、第一个只出现一次的字符:

1、题目:

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).

2、代码实现:

public class Test8 {
	public int FirstNotRepeatingChar(String str) {
		if(str.length()==0){
			return -1;
		}
		
		HashMap<Character, Integer> map = new HashMap<Character,Integer>();
		for(int i=0;i<str.length();i++){
			if(map.containsKey(str.charAt(i))){
				int time = map.get(str.charAt(i));
				map.put(str.charAt(i),++time);
			}else{
				map.put(str.charAt(i), 1);
			}
		}
		
		int pos=-1;
		for(int i=0;i<str.length();i++){
			char c = str.charAt(i);
			if(map.get(c)==1){
				return i;
			}
		}
		return pos;
    }
}

 

 

二、数组中只出现一次的数字:

1、题目:

一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。

2、解题思路:

参考牛客网的“披萨大叔”:https://www.nowcoder.com/questionTerminal/e02fdb54d7524710a7d664d082bb7811

首先:位运算中异或的性质:两个相同数字异或=0,一个数和0异或还是它本身。

当只有一个数出现一次时,我们把数组中所有的数,依次异或运算,最后剩下的就是落单的数,因为成对儿出现的都抵消了。

依照这个思路,我们来看两个数(我们假设是AB)出现一次的数组。我们首先还是先异或,剩下的数字肯定是A、B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位。我们就取第一个1所在的位数,假设是第3位,接着把原数组分成两组,分组标准是第3位是否为1。如此,相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。然后把这两个组按照最开始的思路,依次异或,剩余的两个结果就是这两个只出现一次的数字。

3、代码实现:

public class Test1 {

	//num1,num2分别为长度为1的数组。传出参数
	//将num1[0],num2[0]设置为返回结果
	public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
		 if(array==null ||array.length<2)
           return ;
		 
		 //对数组所有数组进行异或
		 int temp=0;
		 for(int i=0;i<array.length;i++){
			 temp^=array[i];
		 }
		 
		//从左向右移动,获取第一个为1的位数
		 int index=findFirstBits(temp);
		 
		 for(int i=0;i<array.length;i++){
			 if(isBit(array[i],index)){
				 num1[0]^=array[i];
			 }else{
				 num2[0]^=array[i];
			 }
		 }
    }

	
	private boolean isBit(int num, int indexOf1) {
		num = num >>indexOf1;
		return (num & 1) == 1;
	}


	//从左向右移动,获取第一个为1的位数
	private int findFirstBits(int num) {
		int indexBit = 0;
		while((num & 1)==0 && indexBit<(8<<2)){
			num = num>>1;//将num右移1位(也即除以2),然后再将结果赋值给num
			++indexBit;
		}
		
		return indexBit;
	}
}

 

 

三、字符流中第一个不重复的字符:

1、题目:

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符”go”时,第一个只出现一次的字符是”g”。当从该字符流中读出前六个字符“google”时,第一个只出现一次的字符是”l”。

2、解题思路:

一个字符占8位,因此不会超过256个,可以申请一个256大小的数组来实现一个简易的哈希表。时间复杂度为O(n),空间复杂度O(n).

3、代码实现:

public class Test12 {
	//一个字符占8位,因此不会超过256个,可以申请一个256大小的数组来实现一个简易的哈希表。时间复杂度为O(n),空间复杂度O(n).
	int[] hashtable = new int[256];//每一个位置初始值都是0
	StringBuilder builder = new StringBuilder();
	
	 //Insert one char from stringstream
    public void Insert(char ch){
        builder.append(ch);
        hashtable[ch] +=1;
    }
    //return the first appearence once char in current stringstream
    public char FirstAppearingOnce(){
    	char[] str = builder.toString().toCharArray();
    	for(char ch:str){
    		if(hashtable[ch]==1){
    			return ch;
    		}
    	}
    	return '#';
    }
}

 

 

四、数组中重复的数字:

1、题目:

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

2、代码实现:

public class Test22 {

	//第一种方法:
	//不需要额外的数组或者hashtable来保存,题目里写了数组里数字的范围保证在0 ~ n-1 之间,
	//所以可以利用现有数组设置标志,当一个数字被访问过后,可以设置对应位上的数 + n,之后再遇到相同的数时,
	//会发现对应位上的数已经大于等于n了,那么直接返回这个数即可。
	//将第一个重复的数字放在duplication的0号下标中。
	public boolean duplicate(int numbers[],int length,int [] duplication) {

		for(int i=0;i<length;i++){
			int index = numbers[i];
			
			if(index>=length){
				index = index-length;
			}
			if(numbers[index] >= length){
				duplication[0]=index;
				return true;
			}
			numbers[index]=numbers[index]+length;
		}
		return false;
	}
	
	
	//第二种方法:需要重新开拓一个数组
	public boolean duplicate1(int numbers[],int length,int [] duplication) {
		boolean[] k = new boolean[length];
		
		for(int i=0;i<length;i++){
			if(k[numbers[i]]==true){
				duplication[0]=numbers[i];
				return true; 
			}
			k[numbers[i]]=true;
		}
		return false;
	}
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114691.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vue报错cannot read property_vue3 ref 数组

    vue报错cannot read property_vue3 ref 数组当函数执行到this.agents.splice()时,我设置了断点。发现传参index是0,但是页面上的列表项对应的第一行数据没有被删除,WTF!!!这是什么鬼!然后我打开VueDevtools,然后刷新了一下,发现那个数组的第一项还是存在的removeOneAgentByIndex:function(index){this.agents.splice(index,1)…

    2025年11月25日
    4
  • 域渗透之导出域Hash

    域渗透之导出域Hash前言网上采集了一些域内导出NTDS.dit文件的方式Hash值存储在域控制器中(C:\Windows\NTDS\NTDS.DIT)MimikatzMimikatz有一

    2021年12月13日
    58
  • 改变Visual Studio 2012的皮肤建议收藏

    习惯了用vs的绿色背景,vs2012有自己的主题管理工具–ThemeEditorvs2012默认没有安装ThemeEditor,菜单:工具->扩展和更新,搜索栏里面输入ThemeEdit

    2021年12月20日
    40
  • java笔试题大全带答案_java笔试题大全带答案(经典11题)[通俗易懂]

    java笔试题大全带答案_java笔试题大全带答案(经典11题)[通俗易懂]#java笔试题大全带答案(经典11题)**1.不通过构造函数也能创建对象吗()**A.是B.否**分析:答案:A**Java创建对象的几种方式(重要):(1)用new语句创建对象,这是最常见的创建对象的方法。(2)运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。(3)调用对象的clo…

    2022年6月21日
    29
  • 航天金税金税盘批量导入项目开发

    航天金税金税盘批量导入项目开发公司erp要实现发票导入到最新航天金税盘,数据接口文档下载地址:http://download.csdn.net/detail/y281252548/9567083不懂得联系我:免费  qq:281252548

    2022年6月4日
    59
  • 微信聊天内容制作生成器微信小程序源码/支持多种制作生成[通俗易懂]

    ☑️编号:ym205☑️品牌:小程序☑️语言:wx☑️大小:345KB☑️类型:聊天内容制作☑️支持:小程序????欢迎免费领取(注明编号)????✨源码介绍这是一款微信聊天内容制作生成小程序源码,该小程序支持制作多种内容。支持单人聊天模式制作,支持群聊模式制作生成;每一种模式都支持我们微信需要的功能都有,视频,语音,时间,内容等等,大家可以最后看演示图!!另外还支持微信零钱,也就是我的界面制作生成DIY金额(具体大家看演示图);另外也支持微信红包制作DIY金额,发

    2022年4月9日
    176

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号