JAVA代码编写
给定两个字符串 *s*
和 *t*
,编写一个函数来判断 *t*
是否是 *s*
的字母异位词。
**注意:**若 *s*
和 *t*
中每个字符出现的次数都相同,则称 *s*
和 *t*
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和 t
仅包含小写字母进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
教程:https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频:https://www.bilibili.com/video/BV1YG411p7BA
思路:题目中给出字符串都是小写字母a-z,这样就有26个下标,通过字母与‘a’相减,获取下标值,在一个字符串中进行++操作,在另一个字符串中进行–操作,当结果数组中有一个不为0的数,就返回false,否则返回true。很是巧妙。
复杂度分析:
时间复杂度: O(m+n)
空间复杂度: O(1)
class Solution {
public boolean isAnagram(String s, String t) {
int[] record=new int[26];
for(int i=0;i<s.length();i++){
record[s.charAt(i)-'a']++;
}
for(int i=0;i<t.length();i++){
record[t.charAt(i)-'a']--;
}
for(int count:record){
if(count!=0){
return false;
}
}
return true;
}
}
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
教程:https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html
视频:https://www.bilibili.com/video/BV1ba411S7wu
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。
思路:考虑到即使交集是重复的,所以采用Set数据结构,set不包含重复数据,没有顺序。
遍历数组nums1,依次将值存入set1中,实现了去重。然后再遍历数组nums2的时候,查看set1是否包含该值,有的话添加到新的set,最后将set类型转为数组类型返回。
复杂度分析:
时间复杂度: O(logn)
空间复杂度: O(n)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set1= new HashSet<>();
Set<Integer> resSet= new HashSet<>();
for(int i =0;i<nums1.length;i++){
set1.add(nums1[i]);
}
//遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set1.contains(i)) {
resSet.add(i);
}
}
int[] arr = new int[resSet.size()];
int j = 0;
for(int i : resSet){
arr[j++] = i;
}
return arr;
}
}
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例 1:
输入:n = 19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
示例 2:
输入:n = 2
输出:false
提示:
1 <= n <= 231 - 1
教程:https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html
思路:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
一开始疑惑为什么要判断是否出现相同的和,好像可以这么理解,因为你有重复的话,就是死循环,不会有结果是1的情况。
复杂度分析:
时间复杂度: O(1)
空间复杂度: O(1)
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while (n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNumber(n);
}
return n == 1;
}
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
res += temp * temp;
n = n / 10;
}
return res;
}
}
为找工作,我的代码都是用的JAVA,慢慢学习中。
LeetCode刷题Day1
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
**进阶:**你可以想出一个时间复杂度小于 O(n2)
的算法吗?
复杂度分析
时间复杂度: O ( n 2 ) O(n^2) O(n2),这里n为数组的长度。
空间复杂度: O ( 1 ) O(1) O(1),只用到常数个临时变量。
class Solution {
public int[] twoSum(int[] nums, int target) {
int len = nums.length;
for(int i=0;i<len-1;i++){
for(int j=i+1;j<len;j++){
if(nums[i]+nums[j]==target){
return new int[]{i,j};
}
}
}
throw new IllegalArgumentException("No two sum solution");//不写不能通过
}
public static void main(String[ ] args){
int[] arrayName = {2,7,11,15};
Solution s = new Solution();
int[] indexs=s.twoSum(arrayName,9);
for (int i = 0; i < indexs.length; i++) {
System.out.print(indexs[i]+" ");
}
}
}
我自己想到的也是这个暴力破解,因为其他不熟练,但是第一个for循环,我原本写的是(i
new int[]
{1,2,3}int[] nums = new int[5];
nums[0]=1;
int[] nums = Array.create(1, 2, 3, 4, 5);
//使用Array类的静态方法创建和初始化数组:int[] source = {1, 2, 3, 4, 5};
//使用Arrays类的静态方法复制、排序等操作数组:int[] target = Arrays.copyOf(source, source.length);
// 复制数组Arrays.sort(target);
// 对目标数组进行排序对于代码中抛出的异常,要加上这句,是因为,如果数组nums中不存在符合条件的两个数,就不会有返回值,而函数定义的时候,定义的返回类型是int[],会报错,所以需要抛出异常。
再看看这个异常IllegalArgumentException
是非法参数异常,当传递给方法的参数不满足预期时,比如传入了无效的参数或空值,容易引发此异常,如果找不到符合条件的两个数,就抛出这个非法参数异常,错误信息是“No two sum solution”。
在遍历的同时,记录一些信息,以省去一层循环,这是“以空间换时间"的想法
需要记录已经遍历过的数值和它所对应的下标,可以借助查找表实现
查找表有两个常用的实现:
哈希表
平衡二叉搜索树
复杂度分析
class Solution1 {
public int[] twoSum(int[] nums, int target){
int len = nums.length;
Map<Integer,Integer> hashMap = new HashMap<>(len-1);
hashMap.put(nums[0], 0);//这一行也可以不加,因为下面的for循环也会加入的
for (int i = 0; i < len; i++) {
int another = target-nums[i];
if (hashMap.containsKey(another)){
return new int[]{i,hashMap.get(another)};
}
hashMap.put(nums[i],i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
图片来自leetcode官网
思路:定义一个Map存放键值对,默认将nums[0]添加进去(Map这里用put添加元素),官方给出的代码这边初始化了一下,但在for循环中,nums[0]又被加了一下。
public static void main(String[] args) {
Map<Integer,Integer> hashMap = new HashMap<>(5);
hashMap.put(0,1);
hashMap.put(0,1);
for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}//Key: 0, Value: 1
}
我不太了解这个结构,就敲代码试了一下,同样的值加两次,Map他实际第2次会覆盖第1次,应当是按键来存值的,一个键只能一个值。
这里给hashMap赋初值,大概是出于一个程序员的谨慎,就和写文件动不动就ctrl+S一样,hhh。
接着开始遍历,对于nums[0]也就是6,他需要找到一个值为2的,当前Map中没有2,没有就将他存入Map中;对于nums[1]也就是3,他需要找到一个值为5的,当前Map中没有5,没有就将他存入Map中;对于nums[2]也就是8,他需要找到一个值为0的,当前Map中没有0,没有就将他存入Map中;对于nums[3]也就是2,他需要找到一个值为6的,当前Map中有6,找到了,因为题目中说每种输入只会对应一个答案
,找到了就返回new int[]{i,hashMap.get(another)}
。
再思考一下为什么要将数组的下标和值,将值变为map中的键,下标变为map中的值,大概是因为这样好操作,可以根据值得到我们要的下标。脑子不够用,需要理一下思路。
如有错误,请指正!