网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
题目描述:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
示例1
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
1.思路
1.最容易想到的思路:先判断数组的长度是奇数还是偶数,偶数直接返回空,奇数的话先排序,然后遍历数组,找出只出现了一次的数字
2.数学思维:用异或的方法来做,首先要知道,一个数字与其本身异或为0,与0异或还是其数字本身,所以我们设置一个index=0,与数组中的每一个数字异或,因为该数字只出现了一次,所以最后异或得到的结果就是我们要求得数字
3.遍历数组并挨个将元素放进进集合,如果集合中存在这个元素,则将它remove掉,如果不存在则add。按题目的意思,最后这个集合中就只有这个只出现一次的元素了
2.代码
public int singleNumber(int[] nums) {
//方法1:暴力
// Arrays.sort(nums);
// for (int i = 0; i < nums.length-1; i+=2) {
// if (nums[i] != nums[i+2]){
// return nums[i];
// }
// }
// return nums[nums.length-1];
// }
//方法2:异或
int result = 0;
for (int num : nums) {
result ^= num;
}
return result;
//方法3:哈希表
//
// HashSet<Integer> set = new HashSet<>();
// //这样最后的set就只包含这个不重复的元素了
// for(int i = 0; i < nums.length; i++){
// if(set.contains(nums[i])){
// set.remove(nums[i]);
// }else{
// set.add(nums[i]);
// }
// }
// int res = 0;
// for(int i = 0; i < nums.length; i++){
// if(set.contains(nums[i])){
// res = nums[i];
// break;
// }
// }
// return res;
}
2.复制带随机指针的链表
题目描述:给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的深拷贝。深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值.新节点的 next 指针和random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有
x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。 random_index:随机指针指向的节点索引(范围从 0 到
n-1);如果不指向任何节点,则为 null 。 你的代码 只 接受原链表的头节点 head 作为传入参数。
1.思路
1.先说一种简单粗暴的思路:先把链表按照普通链表的方式复制一份,遍历每个节点看该节点random指针指向的位置相对于头节点的偏移量是几(从头结点出发走几步能到达random指向位置),然后根据这个偏移量决定新链表中的每个节点的random的指向,但是改代码比较麻烦
2.更简单而且比较容易理解的方法:创建一个Map<Node,Node> key代表旧链表上的节点,value代表旧链表对应节点的拷贝(也就是新链表的拷贝)
2.代码
public Node copyRandomList(Node head) {
//1.遍历旧链表,把旧链表的每个结点一次插入到map中,key是旧链表,value是拷贝出来得新链表
Map<Node,Node> map=new HashMap<>();
for (Node cur=head;cur != null;cur=cur.next) {
map.put(cur,new Node(cur.val));
}
//2.再次遍历链表,修改新链表节点中的next和random
for (Node cur=head;cur != null;cur=cur.next) {
Node newCur=map.get(cur);
newCur.next=map.get(cur.next);
newCur.random=map.get(cur.random);
}
//返回新链表的头节点
return map.get(head);
}
3.宝石与石头
给你一个字符串 jewels 代表石头中宝石的类型,另有一个字符串 stones 代表你拥有的石头。 stones 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
字母区分大小写,因此 “a” 和 “A” 是不同类型的石头。
示例 1:
输入:jewels = “aA”, stones = “aAAbbbb”
输出:3
示例 2:
输入:jewels = “z”, stones = “ZZ”
输出:0
1.思路
首先对jewels进行遍历,将字符分别存到HashSet中,以便之后遍历stones的时候查找
遍历stones,并将每个字符与HashSet中的进行比对,如果存在,则结果ret++,遍历结束,返回ret
2.代码
public int numJewelsInStones(String jewels, String stones) {
//1.先遍历j边把所有的宝石类加入到一个Set中
Set<Character> set=new HashSet<>();
for (char c:jewels.toCharArray()) {
set.add(c);
}
//2.遍历S拿到每个元素取set中查找,如果能查找就说明是宝石
int ret=0;
for (char c:stones.toCharArray()) {
if (set.contains(c)){
ret++;
}
}
return ret;
}
复杂度分析
时间复杂度:O(m+n),其中 m 是字符串jewels 的长度,n 是字符串 stones 的长度。遍历字符串jewels将其中的字符存储到哈希集合中,时间复杂度是 O(m),然后遍历字符串 stones,对于stones 中的每个字符在 O(1) 的时间内判断当前字符是否是宝石
时间复杂度是: O(n),因此总时间复杂度是 O(m+n)。
空间复杂度:O(m),其中 m 是字符串 jewels 的长度。
4.坏键盘打字
输入描述:
输入在2行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过80个字符的串,由字母A-Z(包括大、小写)、数字0-9、
以及下划线“_”(代表空格)组成。题目保证2个字符串均非空。
输出描述:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有1个坏键。
1.思路
1.循环读入两个字符串,第一个预期输出的内容,第二个实际输出的内容
2.把读入的两个字符串全部转成大写
3.题目中的主要任务是判定预期输出的哪些字符在实际输出的字符串中没有出现
4.先搞一个set把实际输出的每个字符都存进去,就可以遍历预期输出字符串,看看预期中的字符在这个set中出不出现
5. [注意事项]预期字符串中如果有重复的键要去重(可以使用set来去重)
2.代码
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
while (scanner.hasNext()){
//1.循环读入两个字符串,第一个字符串是与其输出的内容;第二个字符串时实际输出的内容
String expected=scanner.next();
String actual=scanner.next();
//2.把读入的两个字符串全都转成大写
expected=expected.toUpperCase();
actual=actual.toUpperCase();
//3.创建一个Set保存实际哪些字符输出了
Set<Character> actualSet=new HashSet<>();
for (int i=0;i < actual.length();i++){
//注意,set中的元素不能重复,如果add的时候发现这个元素已经存在,add就失败了
//没有任何负面影响
actualSet.add(actual.charAt(i));


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.youkuaiyun.com/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.youkuaiyun.com/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**