思路:题目太简单,首尾两指针
错误:
1、题目要求输出的下标从1开始而不是从0
2、Java语言问题 数组初始化、数组长度函数
代码:
class Solution {
public int[] twoSum(int[] numbers, int target) {
int i = 0;
int j = numbers.length-1;
while(i<j){
if(numbers[i] + numbers[j] < target) i++;
else if(numbers[i] + numbers[j] > target) {
j--;
}
else{
break;
}
}
int[] res = new int[2];
res[0] = i+1;
res[1] = j+1;
return res;
}
}
题目:给定一个非负整数 c
,你要判断是否存在两个整数 a
和 b
,使得 a2 + b2 = c
。
思路:题目稍有变化,不能从最后开始,右指针要从开方开始
错误:
1、Java语言问题 类型强制转换、开方函数、求幂函数
2、性能问题 右指针要从开方开始
3、题目初始条件 if (target < 0) return false;
class Solution {
public boolean judgeSquareSum(int c) {
if (target < 0) return false;
int i = 0;
int j = (int)Math.sqrt(c);
boolean res = false;
while(i <= j){
if(i * i + j * j < c) i++;
else if (i * i + j * j > c) j--;
else{
res = true;
break;
}
}
return res;
}
}
思路:双指针,如果都是元音就交换,并且指针同时移动,如果左不是元音,移动左指针,其他情况都移动右指针
错误:
1、交换之后没有移动指针,导致死循环
2、Java语法问题: 数组初始化、char数组和string的互换、string中的元素交换、定位元素、string长度获取。
代码:
class Solution {
public boolean isYuanyin(char a){
if(a == 'a' || a =='o'|| a =='e' || a =='i'|| a =='u'||a == 'A' || a =='O'|| a =='E' || a =='I'|| a =='U') return true;
else return false;
}
public String reverseVowels(String s) {
int i = 0, j = s.length() - 1;
char[] array = s.toCharArray();
while(i < j){
char left = array[i];
char right = array[j];
if(isYuanyin(left) && isYuanyin(right)){
char temp = left;
array[i] = right;
array[j] = temp;
i++;
j--;
}
else if(!isYuanyin(left) && isYuanyin(right)){
i++;
}
else j--;
}
String res = String.valueOf(array);
//String res = new String(array);
return res;
}
}
给定一个非空字符串 s
,最多删除一个字符。判断是否能成为回文字符串。
输入: s = "aba"
输出: true
看了答案
思路:双指针,左右两边都可以去掉字符,如果出现了不同,去掉右边的或者去掉左边的字符,然后判断剩下的是否是回文
错误:
思路问题,没有考虑左右的问题,我的想法是如果左右两个不同,那么就比较两种情况:i+1和j或者i和j-1,然后用num来标记去掉了几个,如果num>=2 的话,那么就说明不回文,这个思路存在两个问题
(1)先进行第一种比较,后比较第二种,这样左右就是不公平的
(2)如果不相同的话,else中无法继续进行下去
后来又想到了递归的思路,但是递归无法找到出口
class Solution {
public boolean validPalindrome(String s) {
int i = 0, j = s.length() - 1;
int num = 0;
while(i < j){
char left = s.charAt(i);
char right = s.charAt(j);
if (left == right){
i++;
j--;
}
else{
return isValid(s, i+1, j)||isValid(s, i, j-1);
}
}
return true;
}
public boolean isValid(String s, int i, int j){
while (i<j){
if (s.charAt(i) == s.charAt(j)){
i++;
j--;
}
else return false;
}
return true;
}
}
思路和错误:
我的思路:
另外建立一个数组存储两者的比较结果 ,并且从头开始进行插入
例题思路:
从后开始比较,并直接存入,因为题目定义nums1存在这么多空间
思路中要有前后的思想
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i=m-1, j=n-1, k=m+n-1;
while(i>=0 || j>=0){
if(i<0){
nums1[k--] = nums2[j--];
}
else if(j<0){
break;
}
else if(nums1[i]>nums2[j]){
nums1[k--] = nums1[i--];
}
else{
nums1[k--] = nums2[j--];
}
}
}
}
2021/4/1
思路:快慢指针
关键:
1、只要指针非空,必有next,考虑不能太复杂
2、static下怎么使用非静态方法:实例化!!!!!!
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null){
return false;
}
ListNode L1 = head;
ListNode L2 = head.next;
while(L1 != null && L2 != null && L2.next != null){
if(L1 == L2) return true;
L1 = L1.next;
L2 = L2.next.next;
}
return false;
}
}
`
2021/4/1
给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串
思路:双指针
思路错误:
1、没有判断now是不是s 的子串(题目理解不透彻)
2、不知道什么是字典顺序 compareTo()
3、如果没有匹配的,忘记返回空字符串 -->""而不是null(边界判断)
技术缺陷:
1、List实例化和初始化
2、字典顺序比较方法
3、字符串长度获取和List长度获取不同
class Solution {
public String findLongestWord(String s, List<String> dictionary) {
int maxlen = 0, maxorder = -1;
for (int k = 0; k < dictionary.size() ; k++) {
String now = dictionary.get(k);
int len = 0, i = 0, j = 0;
while (j < now.length() && i < s.length()){
if (s.charAt(i) == now.charAt(j)){
i++;
j++;
len++;
}
else i++;
}
if (j != now.length()){
continue;
}
if (len > maxlen) {
maxlen = len;
maxorder = k;
}
else if (len == maxlen){
maxorder = now.compareTo(dictionary.get(maxorder))>0?maxorder:k;
}
}
if(maxorder == -1) return "";
else return dictionary.get(maxorder);
}
}
思路:找到基准数(开始位置的数),前后双指针,分别找到比基准大和比基准小的数的位置,将两数进行交换,递归进行排序。最后,将前指针的数放到基准数位置(开始位置),然后将基准数放到前指针这里。
public void sortQ(int[] nums, int start, int end){
if (start > end) return;
int temp = nums[start], i = start, j = end;
while( i < j && i >= 0 && j < nums.length){
while (nums[j] >= temp && i<j){
j--;
}//先让j往前走,因为最后要交换i和start
while (nums[i] <= temp && i<j){
i++;
}
if (i < j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}//当找到左边比temp大,右边比temp小的数的时候,两者交换
}
nums[start] = nums[i];//将i交换到开始,因为nums[i]一定小于temp
nums[i] = temp; //然后将temp放到i这里
sortQ(nums, start, i-1);
sortQ(nums, i+1, end);
}
思路:桶排序
1、使用map键值对存储数据, 注意map的一些操作
2、空间换时间,使用下标来表示次数,并在每个位置存储一个List,每个List存储所有出现这么多次的数
3、从后面开始遍历到第k个数,将所有满足要求的数存储到一个数组中
public static int[] getK(int[] nums, int k){
Map<Integer, Integer> m = new HashMap<>();
// map字典
for (int num : nums){
m.put(num, m.getOrDefault(num,0) + 1);
// 使用map形式存储各个数字的出现次数,如果键在字典中没有出现,那么
// 设定其Default为0,如果出现,则获取该键的值(数字的出现次数)+1,
// 并重新赋值
}
List<Integer>[] bucket = new ArrayList[nums.length+1];
//注意这个定义,每个bucket中存的是一个list
for (int key : m.keySet()){
int val = m.get(key);
if (bucket[val] == null){
bucket[val] = new ArrayList<>();
}
bucket[val].add(key);
}
//bucket就是桶,每个桶的下标代表出现的次数
List<Integer> resList = new ArrayList<>();
//最终结果List
for (int i = bucket.length - 1; i > 0 ; i--) {
if (k == 0){
break;
}
if (bucket[i] == null){
continue;
//如果桶中该值对应元素为空,就继续
}
for (int n : bucket[i]){
resList.add(n);
//如果不为空的话,就获取该次数下的元素
k--;
}
}
int[] result = new int[resList.size()];
for (int i = 0; i < result.length; i++) {
result[i] = resList.get(i);
}
//将list转化为需啊哟的数组格式返回
return result;
}
快速排序练习,注意一定要让j先移动
if (i > j){
return;
}
int start = i, end = j;
int mid = nums[i];
while (i < j){
while (nums[j] >= mid && i<j){
j --;
}
while(nums[i] <= mid && i<j){
i ++;
}
if (i < j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
nums[start] = nums[i];
nums[i] =mid;
Qsort(nums, start, i - 1);
Qsort(nums, i + 1, end);
}