1.两数之和--easy
给定一个整数数组
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- 只会存在一个有效答案
我的题解:
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] a=new int[2];
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
a[0]=i;
a[1]=j;
}
}
}
return a;
}
}
思路:
- 遍历数组,使用target减数组里的值,看看这个结果是否在哈希表中。
- 不在,将这个值和key存入哈希表
- 在,则找到了结果,将结果返回。
- 在这里,key是数组的值,value是数组的下标。
- 如果最终都没有结果则抛出异常
2.有效的字母异位词--easy
给定两个字符串
*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 * 104s和t仅包含小写字母
题解:
class Solution {
public boolean isAnagram(String s, String t) {
int[] arr=new int[26];
for(int i=0;i<s.length();i++){
arr[s.charAt(i)-'a']+=1;
}
for(int i=0;i<t.length();i++){
arr[t.charAt(i)-'a']-=1;
}
for(int i=0;i<26;i++){
if(arr[i]!=0){
return false;
}
}
return true;
}
}
思路:
3.赎金信--easy
给你两个字符串:
ransomNote和magazine,判断ransomNote能不能由magazine里面的字符构成。如果可以,返回
true;否则返回false。
magazine中的每个字符只能在ransomNote中使用一次。示例 1:
输入:ransomNote = "a", magazine = "b" 输出:false示例 2:
输入:ransomNote = "aa", magazine = "ab" 输出:false示例 3:
输入:ransomNote = "aa", magazine = "aab" 输出:true提示:
1 <= ransomNote.length, magazine.length <= 105ransomNote和magazine由小写英文字母组成
题解:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr=new int[26];
for(int i=0;i<magazine.length();i++){
arr[magazine.charAt(i)-'a']+=1;
}
for(int i=0;i<ransomNote.length();i++){
arr[ransomNote.charAt(i)-'a']-=1;
}
for(int i=0;i<26;i++){
if(arr[i]<0){
return false;
}
}
return true;
}
}
思路:
同有效的字母异位词
4.数组的交集--easy
给定两个数组
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] 也是可通过的
题解:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] arr=new int[1001];
Set<Integer> set = new HashSet<>();
int a=0;
for(int i=0;i< nums1.length;i++){
arr[nums1[i]]=1;
}
for(int i=0;i< nums2.length;i++){
if (arr[nums2[i]]==1) {
arr[nums2[i]]-=1;
set.add(nums2[i]);
}
}
int[] arr2=new int[set.size()];
int j=0;
for(int i : set){
arr2[j++] = i;
}
return arr2;
}
}
思路:
- 还是利用桶排的思想,定义大小为1001的数组,如果有值,则将数组里对应的值变为一
- 再循环遍历第二个数组,找到值为一,将其存到一个集合之中(防止重复),然后将值减一
- 最后将集合转变为数组
5.快乐数--easy
编写一个算法来判断一个数
n是不是快乐数。「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果
n是 快乐数 就返回true;不是,则返回false。示例 1:
输入:n = 19 输出:true 解释: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1示例 2:
输入:n = 2 输出:false提示:
1 <= n <= 231 - 1
题解1-----使用哈希表:
class Solution {
public boolean isHappy(int n) {
Set<Integer> set=new HashSet<>();
//如果新求得的数在哈希表中,证明循环
while (n!=1 && !set.contains(n)){
set.add(n);
n=getSum(n);
}
return n==1;
}
public int getSum(int n){
int sum=0;
while(n>0){
sum+=(n%10)*(n%10);
n=n/10;
}
return sum;
}
}
思路:
题上已知无限循环,则将每次求得的平方和存入哈希表中
- 如果新求得的数在哈希表中,证明循环
- 如果结果为1,则是快乐数
题解2----使用快慢指针:
class Solution {
public boolean isHappy(int n) {
int fast=n,slow=n;
do {
slow=getSum(slow);
fast=getSum(fast);
fast=getSum(fast);
}while (fast!=slow);
return fast==1;
}
public int getSum(int n){
int sum=0;
while(n>0){
sum+=(n%10)*(n%10);
n=n/10;
}
return sum;
}
}
思路:
循环问题使用快慢指针一般可以解决,只要数据规模不是很大 在int中199999999的位数的平方和为最大为:1+81*9=720 所以快乐数的取值范围为[1,720]; 所以一定会出现循环, 又因为1的快乐数为1,本身就是一个循环
所以循环只有两种可能
- 多个数循环
- 1自身循环
6.有序数组的平方----easy
给你一个按 非递减顺序 排序的整数数组
nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。示例 1:
输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100]示例 2:
输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]提示:
1 <= nums.length <= 104-104 <= nums[i] <= 104nums已按 非递减顺序 排序
题解1----暴力解法
class Solution {
public int[] sortedSquares(int[] nums) {
int[] s=new int[nums.length];
for(int i=0;i< nums.length;i++){
s[i]=nums[i]*nums[i];
}
Arrays.sort(s);
return s;
}
}
题解2----双指针(最优解)
class Solution {
public int[] sortedSquares(int[] nums) {
int[] s=new int[nums.length];
int l=0,r= nums.length-1,i= nums.length-1;
while (l<=r){
int re=nums[r]*nums[r];
int le=nums[l]*nums[l];
if(re>le){
s[i]=re;
i--;
r=r-1;
}else{
s[i]=le;
i--;
l=l+1;
}
}
return s;
}
}
思路:
- 定义左右两个指针,向中间走
- 比较其大小,将大的放在最大位置
7.三数之和----medium
给你一个整数数组
nums,判断是否存在三元组[nums[i], nums[j], nums[k]]满足i != j、i != k且j != k,同时还满足nums[i] + nums[j] + nums[k] == 0。请你返回所有和为
0且不重复的三元组。注意: 答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。提示:
3 <= nums.length <= 3000-105 <= nums[i] <= 105
题解:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
// 找出a + b + c = 0
// a = nums[i], b = nums[l], c = nums[r]
int l=0,r=0;
for(int i=0;i< nums.length;i++){
if (nums[0] > 0) {
return res;
}
if (i>0&&nums[i]==nums[i-1]){//去重a
continue;
}
l=i+1;
r=nums.length-1;
while(l<r){
int sum=nums[i]+nums[l]+nums[r];
if(sum>0){
r--;
}else if (sum<0){
l++;
}else {
res.add(Arrays.asList(nums[i],nums[l],nums[r]));
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while(r>l && nums[r]==nums[r-1]) r--;
while(r>l && nums[l]==nums[l+1]) l++;
r--;
l++;
}
}
}
return res;
}
}
思路:
8.四数之和----medium
给你一个由
n个整数组成的数组nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]](若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]提示:
1 <= nums.length <= 200-109 <= nums[i] <= 109-109 <= target <= 109
题解:
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
// 找出a + b + c + d= 0
// a = nums[i], b = nums[j],c = nums[l], d = nums[r]
for(int i=0;i< nums.length;i++){
//初始值大于,则没机会
if (nums[i] > target&&nums[i] > 0) {
return res;
}
if (i > 0 && nums[i - 1] == nums[i]) { // 对nums[i]去重
continue;
}
for (int j=i+1;j< nums.length;j++){
if (j > i + 1 && nums[j - 1] == nums[j]) { // 对nums[j]去重
continue;
}
int left = j + 1;
int right = nums.length - 1;
while (right > left) {
// nums[k] + nums[i] + nums[left] + nums[right] > target int会溢出
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
res.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
// 对nums[left]和nums[right]去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return res;
}
}
思路:
同三数之和
10.同构字符串----easy
给定两个字符串
s和t,判断它们是否是同构的。如果
s中的字符可以按某种映射关系替换得到t,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
示例 1:
输入:s = "egg", t = "add" 输出:true示例 2:
输入:s = "foo", t = "bar" 输出:false示例 3:
输入:s = "paper", t = "title" 输出:true提示:
1 <= s.length <= 5 * 104t.length == s.lengths和t由任意有效的 ASCII 字符组成
题解:
class Solution {
public boolean isIsomorphic(String s, String t) {
Map<Character, Character> map1 = new HashMap<>();
Map<Character, Character> map2 = new HashMap<>();
for (int i = 0, j = 0; i < s.length(); i++, j++) {
if (!map1.containsKey(s.charAt(i))) {
map1.put(s.charAt(i), t.charAt(j)); // map1保存 s[i] 到 t[j]的映射
}
if (!map2.containsKey(t.charAt(j))) {
map2.put(t.charAt(j), s.charAt(i)); // map2保存 t[j] 到 s[i]的映射
}
// 无法映射,返回 false
if (map1.get(s.charAt(i)) != t.charAt(j) || map2.get(t.charAt(j)) != s.charAt(i)) {
return false;
}
}
return true;
}
}
思路:
11.查找公用字符----easy
给你一个字符串数组
words,请你找出所有在words的每个字符串中都出现的共用字符( 包括重复字符),并以数组形式返回。你可以按 任意顺序 返回答案。示例 1:
输入:words = ["bella","label","roller"] 输出:["e","l","l"]示例 2:
输入:words = ["cool","lock","cook"] 输出:["c","o"]提示:
1 <= words.length <= 1001 <= words[i].length <= 100words[i]由小写英文字母组成
题解:
class Solution {
public List<String> commonChars(String[] A) {
List<String> result = new ArrayList<>();
if (A.length == 0) return result;
int[] hash= new int[26]; // 用来统计所有字符串里字符出现的最小频率
for (int i = 0; i < A[0].length(); i++) { // 用第一个字符串给hash初始化
hash[A[0].charAt(i)- 'a']++;
}
// 统计除第一个字符串外字符的出现频率
for (int i = 1; i < A.length; i++) {
int[] hashOtherStr= new int[26];
for (int j = 0; j < A[i].length(); j++) {
hashOtherStr[A[i].charAt(j)- 'a']++;
}
// 更新hash,保证hash里统计26个字符在所有字符串里出现的最小次数
for (int k = 0; k < 26; k++) {
hash[k] = Math.min(hash[k], hashOtherStr[k]);
}
}
// 将hash统计的字符次数,转成输出形式
for (int i = 0; i < 26; i++) {
while (hash[i] != 0) { // 注意这里是while,多个重复的字符
char c= (char) (i+'a');
result.add(String.valueOf(c));
hash[i]--;
}
}
return result;
}
}
思路:
很简单,看题了就会了