Leetcode java 入门2
1365. 有多少小于当前数字的数字
给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。
换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。
以数组形式返回答案。
输入:nums = [8,1,2,2,3]
输出:[4,0,1,1,3]
暴力解法
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int leslie;
int jk=0;
int [] faye=new int [nums.length];
for (int i=0;i<nums.length;i++){
leslie=0;
for (int j=0;j<nums.length;j++){
if (j!=i){
if (nums[j]<nums[i])
leslie++;
}
}
faye[jk]=leslie;
jk++;
}
return faye;
}
}
时间:O(n^2) 空间O(1)
2.计数排序
public int[] smallerNumbersThanCurrent(int[] nums) {
int [] faye= new int [101];
for (int i = 0; i < nums.length; i++) {
faye[nums[i]] +=1; //统计数字出现频率{0,1,2,1,0,0,0,0,1}
}
for (int i = 1; i < faye.length; i++) {
faye[i] += faye[i-1]; //{0,1,3,4,4,4,4,4,5} 累加前面数
} // 0 1 2 3 4 5 6 7 8
for (int i = 0; i < nums.length; i++) {
nums[i] = nums[i]!=0 ? faye[nums[i]-1] : 0;
} //找到累加数组的前一个数即为前面小于它的数的总和
return nums;
}
时间复杂度:O(N + K),其中 K 为(数组)值域大小。需要遍历两次原数组,同时遍历一次频次数组找出前缀和。
空间复杂度:O(K),因为要额外开辟一个值域大小的数组。
3.排序加哈希图
class Solution {
public static int[] smallerNumbersThanCurrent(int[] nums) {
int [] faye=Arrays.copyOf(nums, nums.length); //数组复制
Arrays.sort(faye);// {1,2,2,3,8}
HashMap<Integer, Integer> leslie = new HashMap<>();
for (int i = faye.length-1; i >=0; i--) {
leslie.put(faye[i], i); //相同的数被赋予下标
//(8,4)(3,3)(2,2)(2,1)(1,0)
//从后往前排 同样值必须让低索引覆盖高索引 索引计算排第几才有意义
}
for (int i = 0; i < faye.length; i++) {
nums[i]=leslie.get(nums[i]);//nums里的数值对应hash表的key输出value
}
return nums;
}
}
时间复杂度 O(nlog(n)),空间复杂度 O(n)
解释
1.Arrays.sort()排序的复杂度为O(nlog(n))。
2.开辟了Faye的新数组空间为N
3.Arrays.copyOf(les[], les.length) 完全复制一个新数组
1002.查找常用字符
给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。
你可以按任意顺序返回答案。
输入:[“bella”,“label”,“roller”]
输出:[“e”,“l”,“l”]
1.字符计数解法
涉及Linklist 双向链表,计数排序
Character.toString(char)方法char->String
s.toCharArray() 转字符串为字符数组
import java.util.List;
//如果是import java.awt.List;报错类型 List 不是通用的,不能使用参数() 将它参数化
public static List commonChars(String[] A) {
int [] leslie = getAs(A[0]); //把[0]字符串 转为计数频率数组
List<String> faye=new LinkedList<String>();
for (int i = 1; i < A.length; i++) {
int [] leslie2 = getAs(A[i]); //找到第二组字符串{0111010}
for (int j = 0; j < leslie.length; j++) {
if(leslie[j]>leslie2[j]) //只要leslie2的值不为0,就会保证leslie中出现过相同字符。
leslie[j]=leslie2[j];//如果leslie2有值为0,则leslie相应的值为0。
}
}//for 循环后得到一组计算数组 记录字符串的频率。
for (int j = 0; j < leslie.length; j++) {
String e=null;
//if(leslie[j]>0)
while(leslie[j]-- >0)//成功解决出现两次字母的问题 判断>0再自--判断
{
// Character.toString(char)方法char->String
e=Character.toString((char) (j+'a')); //int j + 'a' 强制类型转换会变成整数
faye.add(e);
}
}
return faye;
}
private static int[] getAs(String s) { //统计字符出现次数
int [] faye= new int [26];
for (char i : s.toCharArray())
{ //s.toCharArray() 转字符串为字符数组
faye[i-'a']++;
}
return faye;
}
Java中的集合类的关系图
ArrayList与LinkedList区别
349.两个数组的交集
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> faye = new HashSet<>();
Set<Integer> faye1 = new HashSet<>();
Set<Integer> faye2 = new HashSet<>();
int k= 0;
// Integer []leslie = new Integer [nums2.length];
for (int i = 0; i < nums1.length; i++) {
faye.add(nums1[i]);
}
for (int i = 0; i < nums2.length; i++) {
faye1.add(nums2[i]);
}
faye2.addAll(faye);
faye2.retainAll(faye1);//取集合交集
int []leslie = new int [faye2.size()];
for (int a : faye2) {
leslie[k]=a;
k++;
}
//leslie=faye2.toArray(new Integer[0]);
//对象无法转类型
return leslie;
}
}
136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
输入: [4,1,2,1,2]
输出: 4
1.暴力解法
public static int singleNumber(int[] nums) {
int leslie=0;
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
if(i==j) //避免自身比较
continue;
if (nums[i]==nums[j]) {
leslie=1; //哨兵找到相同元素
break;
}
else leslie=0; //如果不置0 [2,2,1] 1的值无法找到
}
if (leslie==0)
return nums[i];
}
return 0;
}
第一次写暴力解法花了40分钟!
2.异或运算
解题思路:
0⊕a =a
a⊕b⊕c =a⊕c⊕b(交换率)
4⊕3⊕5⊕3⊕4 等价于(4⊕4⊕3⊕3)⊕5 等价于0 ⊕ 5
题目中每个元素均出现两次 则满足上式子
class Solution {
public static int singleNumber(int[] nums) {
int faye = 0;
for (int i : nums) {
faye ^= i;
}//0异或任何数都为原值
return faye;
}
}
异或时间复杂度为O(n),空间复杂度为O(1)
3.HashMap实现
public static int singleNumber(int[] nums) {//[4,1,2,1,2]
HashMap<Integer,Integer> leslie = new HashMap<>();
for (int i : nums) { //间接计数排序 (4,1) (1,2) (2,2)
Integer count = leslie.get(i); //值如果不存在 则为null
count = count == null? 1: ++count;//如果count++,则会把count赋给count,再加一导致bug。
leslie.put(i, count); //(1,2) 会覆盖 (1,1)
}
for (int j : leslie.keySet()) {//map.keySet()返回一个由键组成的集合
if(leslie.get(j)==1)//值为1 则返回键key
return j;
}
return -1;
}