H指数
先对数组排序,然后从大的一头开始遍历,只要数组当前的数比现在的h指数大就给h指数+1,直到数组当前的数比现在的h指数小的时候结束,这时h的值就是要返回的结果。
|-----|---|---|---|---|---|
| 排序前 | 3 | 0 | 6 | 1 | 5 |
| 排序后 | 0 | 1 | 3 | 5 | 6 |
| h值 | # | # | 3 | 2 | 1 |
public int hIndex(int[] citations) {
Arrays.sort(citations);
int i = citations.length-1;
int h = 0;
while(i>=0&&citations[i]>h){
h++;
i--;
}
return h;
}
O(1) 时间插入、删除和获取随机元素
380. O(1) 时间插入、删除和获取随机元素 - 力扣(LeetCode)
通过一个map和一个数组来实现
插入:map<Integer,Integer> (<值,在数组的下标>) list存值
删除:不光需要将目标值删除,还需要将删除后空出来的地方进行填补,不然后面的获取随机元素会出错。填补流程如下。
class RandomizedSet {
private Map<Integer,Integer> map ;
private List<Integer> list;
public RandomizedSet() {
map = new HashMap<>();
list = new ArrayList<>();
}
public boolean insert(int val) {
if(map.containsKey(val)){
return false;
}
map.put(val,list.size());
list.add(val);
return true;
}
public boolean remove(int val) {
if(!map.containsKey(val)){
return false;
}
int a = map.get(val);
int last = list.get(list.size()-1);
list.set(a,last);
map.put(last,a);
list.remove(list.size()-1);
map.remove(val);
return true;
}
public int getRandom() {
Random random = new Random();
int randomNumber = random.nextInt(list.size());
return list.get(randomNumber);
}
}
除自身以外数组的乘积
238. 除自身以外数组的乘积 - 力扣(LeetCode)
要求时间复杂度为O(N),且不能用除法,所以我们可以进行两次遍历,第一次遍历将每个位置左边的所有数的乘积计算出来,第二次遍历把每个位置右边的所有数的乘积计算出来,最后相乘即可。
public static int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] arr1 = new int[n];
int[] arr2 = new int[n];
int res = 0;
arr1[0] = 1;
arr2[n-1] = 1;
for (int i = 1; i < n; i++) {
arr1[i]=arr1[i-1]*nums[i-1];
}
// System.out.println(Arrays.toString(arr1));
for (int i = n-2; i >= 0; i--) {
arr2[i]=arr2[i+1]*nums[i+1];
}
// System.out.println(Arrays.toString(arr2));
for (int i = 0; i < n; i++) {
nums[i]=arr1[i]*arr2[i];
}
return nums;
}
加油站
主要的两个变量,left(记录当前剩余的汽油量,用来判断起始点),sum(记录总油量是否大于耗油量),每当left<0时,则说明前边的节点都不可用,让现在节点的下一个节点作为新的起始点,并将当前剩余油量left重置为0,遍历完数组,判断sum是否小于0,是则返回-1,不是则返回现在的起始节点。
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
int left = 0;
int sum = 0;
int index = 0;
for (int i = 0,p; i < n; i++) {
p = gas[i]-cost[i];
left += p;
sum += p;
if(left<0){
left = 0;
index = i+1;
}
}
return sum < 0 ? -1 : index;
}
罗马数字转整数
先写一个获取对应的字符值的方法,然后找一个变量记录前一个字符对应的值,每次比较当前字符的值与前一个字符的值的大小,分为两种情况,当前>之前,则是类似于"IV",则结果应该减去前一个字符对应值,若当前<=之前,则对应的是类似于"II"或者"VI",则应该加上前一个字符对应值,最后不要忘记加上最后一个字符的值。
public static int romanToInt(String s) {
int res = 0;
int pre = 0;
pre = getnumber(s.charAt(0));
int n = s.length();
for (int i = 1; i < n; i++) {
int index = getnumber(s.charAt(i));
if (pre<index){
res-=pre;
}else{
res+=pre;
}
pre = index;
}
res += pre;
return res;
}
public static int getnumber(char ch){
switch (ch){
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return 0;
}
}
整数转罗马数字
这个没什么说的,直接看代码就好了。
public String intToRoman(int num) {
StringBuilder str = new StringBuilder();
while(num>=1000){
str.append("M");
num-=1000;
}
if (num>=900){
str.append("CM");
num-=900;
}
if (num>=500){
str.append("D");
num-=500;
}
if (num>=400){
str.append("CD");
num-=400;
}
while (num>=100){
str.append("C");
num-=100;
}
if (num>=90){
str.append("XC");
num-=90;
}
if (num>=50){
str.append("L");
num-=50;
}
if (num>=40){
str.append("XL");
num-=40;
}
while (num>=10){
str.append("X");
num-=10;
}
if (num>=9){
str.append("IX");
num-=9;
}
if (num>=5){
str.append("V");
num-=5;
}
if (num>=4){
str.append("IV");
num-=4;
}
while (num>=1){
str.append("I");
num-=1;
}
return str.toString();
}
最后一个单词的长度
第一次循环找到不为' '的起点,第二次循环第一次遇到' '停止。
public int lengthOfLastWord(String s) {
int count = 0;
int index = s.length()-1;
while (s.charAt(index)==' '){
index--;
}
while (index>=0&&s.charAt(index)!=' '){
index--;
count++;
}
return count;
}
最长公共前缀
将第一个字符串当作公共前缀,对每个字符串进行匹配判断,如果与当前公共前缀不符,则将公共前缀长度-1,循环判断,直到当前公共前缀符合或者公共前缀长度为0。
public String longestCommonPrefix(String[] strs) {
if (strs==null||strs.length==0) {
return "";
}
String pre = strs[0];
for (int i = 1; i < strs.length; i++) {
while (strs[i].indexOf(pre) !=0){
pre = pre.substring(0,pre.length()-1);
if (pre.length()==0){
return "";
}
}
}
return pre;
}
翻转字符串中的单词
从后向前遍历,使用双指针来确定单词的范围。
public static String reverseWords(String s) {
StringBuilder str = new StringBuilder();
s = s.trim();
int n = s.length();
int l = n-1;
int r = n-1;
while (l>=0){
while (l>=0&&s.charAt(l)!=' '){
l--;
}
str.append(s.substring(l+1,r+1)+" ");
while (l>=0&&s.charAt(l)==' '){
l--;
}
r=l;
}
return str.toString().trim();
}
找出字符串中第一个匹配项的下标
28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
直接暴力解决吧,想提升可以使用KPM
public int strStr(String haystack, String needle) {
int n = haystack.length(), m = needle.length();
for (int i = 0; i + m <= n; i++) {
boolean flag = true;
for (int j = 0; j < m; j++) {
if (haystack.charAt(i + j) != needle.charAt(j)) {
flag = false;
break;
}
}
if (flag) {
return i;
}
}
return -1;
}
Z字形态变换
使用列表,将每一行的字符加入自己所在行对应的字符串中,用一个标志量来确定方向,到头就转向。
public String convert(String s, int numRows) {
if(numRows < 2) return s;
List<StringBuilder> rows = new ArrayList<StringBuilder>();
for(int i = 0; i < numRows; i++) rows.add(new StringBuilder());
int i = 0, flag = -1;
for(char c : s.toCharArray()) {
rows.get(i).append(c);
if(i == 0 || i == numRows -1) flag = - flag;
i += flag;
}
StringBuilder res = new StringBuilder();
for(StringBuilder row : rows) res.append(row);
return res.toString();
}