本文是小菜鸡的练习记录,参考了大佬的笔记 https://leetcode.wang/leetCode-1-Two-Sum.html
一、两数之和 two sum
解法一:暴力解法两层循环
class Solution {
public int[] twoSum(int[] nums, int target) {
int []ans=new int[2];
for(int i = 0; i < nums.length; i++){
for(int j = 0;j<nums.length; j++){
if(nums[i] + nums[j] == target){
ans[0] = i;
ans[1] = j;
return ans;
}
}
}
return ans;
}
}
没想到的点:返回值用一个数组放置。首先定义一个ans[2],之后用它来返回下标。
解法二:对第二层循环进行改进
class Solution {
public int[] twoSum(int[] nums, int target) {
int []ans=new int[2];
for(int i = 0; i < nums.length; i++){
// 这里将j初始值设为i+1,因为[i,i-1]的组合已经在i = i-1的时候遍历过了,所以可以直接从j = i+1开始
for(int j = (i + 1);j<nums.length; j++){
if(nums[i] + nums[j] == target){
ans[0] = i;
ans[1] = j;
return ans;
}
}
}
return ans;
}
}
解法三:对if判断语句做变化
class Solution {
public int[] twoSum(int[] nums, int target) {
int []ans=new int[2];
for(int i = 0; i < nums.length; i++){
for(int j = (i + 1);j<nums.length; j++){
// 这里进行改变,不求和判断了,改成理应的差值与nums[j]作比较
int sub = target - nums[i];
if( nums[j] == sub){
ans[0] = i;
ans[1] = j;
return ans;
}
}
}
return ans;
}
}
解法四:使用hashmap
将数组中的值作为key,将下标作为value
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
map.put(nums[i],i);
}
for(int j = 0;j < nums.length; j++){
int sub = target - nums[j];
// 这里要注意排除掉某个数本身,因为同一个数不能使用两次
if( map.containsKey(sub) && map.get(sub) != j){
return new int[]{j,map.get(sub)};
}
}
return null;
}
}
解法五:想不到
这个解法把解法四的循环合二为一,并且没有想到可以将map.put放在if语句后面。
这样可以不用判断满足条件的是否为当前元素的情况,因为当前元素还没有被放进map里。
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int sub = target - nums[i];
if(map.containsKey(sub)){
return new int[]{map.get(sub),i};
}
map.put(nums[i],i);
}
return null;
}
}
二、 长度为三且各字符不同的子字符串(1876)
解法一:暴力解法
class Solution {
public int countGoodSubstrings(String s) {
int num = 0;
// 一开始出错在这里的length-2 因为是"i<" 取不到length-3,所以要改成减二
for(int i = 0;i < s.length() - 2;i++){
String zi = s.substring(i,i+3);
if(zi.charAt(0) != zi.charAt(1) && zi.charAt(0) != zi.charAt(2) && zi.charAt(1) != zi.charAt(2)){
num += 1;
}
}
return num;
}
}
总结:①字符串取其中的某几个字符的方法:“asdfghj”.substring(1,5)取的是"sdfg".左闭右开.可参考 https://blog.youkuaiyun.com/billxin0621/article/details/98485271
②取字符串中某一个位置的字符,用s.charAt()
参考http://www.qidianbaike.com/post/49102.html
三、设计停车系统(1603)
参考:https://www.pudn.com/news/6254433347503a0a93a3fb73.html
解法一:暴力解法
// 首先是一个停车场类
class ParkingSystem {
int big,medium,small;
//在 ParkingSystem类中实现big,medium,small的初始化
public ParkingSystem(int big, int medium, int small) {
this.big = big;
this.medium = medium;
this.small = small;
}
//判断停车场内是否有余位置
public boolean addCar(int carType) {
if(carType == 1){
if(big > 0){
big --;
return true;
}else{
return false;
}
}else if(carType == 2){
if(medium > 0){
medium --;
return true;
}else{
return false;
}
}else if(carType == 3){
if(small > 0){
small --;
return true;
}else{
return false;
}
}
return true;
}
}
方法二:简化方法一
去掉了FALSE判断,但是最后这里要改成return false
class ParkingSystem {
int big,medium,small;
public ParkingSystem(int big, int medium, int small) {
this.big = big;
this.medium = medium;
this.small = small;
}
public boolean addCar(int carType) {
if(carType == 1){
if(big > 0){
big --;
return true;
}
}else if(carType == 2){
if(medium > 0){
medium --;
return true;
}
}else if(carType == 3){
if(small > 0){
small --;
return true;
}
}
return false;
}
}
四、执行操作后的变量值
解法一:暴力解法
class Solution {
public int finalValueAfterOperations(String[] operations) {
int x = 0;
for(int i = 0; i < operations.length; i++){
// 这里一开始用的“==”,结果不对才想到用equals
if( "--X".equals(operations[i]) || "X--".equals(operations[i])){
x -= 1;
}else if("++X".equals(operations[i]) || "X++".equals(operations[i])){
x += 1;
}
}
return x;
}
}
总结:equals和==用法区别:一个是指内存地址 一个指值
String s=“abcd"是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径。以String s=“abcd”;形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。 这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象, 如果没有,则在常量池中新创建一个"abcd”,下一次如果有String s1 = “abcd”;又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象.
参考:https://blog.youkuaiyun.com/qq_44580803/article/details/123556176
五、基于排列构建数组(1920)
解法一:暴力解法
class Solution {
public int[] buildArray(int[] nums) {
int length = nums.length;
int[] ans = new int[length];
for(int i = 0; i < length;i++){
ans[i] = nums[nums[i]];
}
return ans;
}
}
六、 回文数(9.)
解法一:暴力解法,将int转换成string判断字符串是否相等
class Solution {
public boolean isPalindrome(int x) {
// 先将x转换成字符串
String s = String.valueOf(x);
// 准备一个空string 用来放倒置之后的字符串
String t = "";
// 倒置拼接
for(int i = s.length()-1;i >= 0; i--){
t += s.charAt(i);
}
if(t.equals(s)){
return true;
}else{
return false;
}
}
}
缺点:运行效率低
解法二:大佬的妙思
class Solution {
public boolean isPalindrome(int x) {
if (x == 0) return true;
if (x < 0 || x % 10 == 0) return false;
int reversed = 0;
while (x > reversed) {
reversed = reversed * 10 + x % 10;
x /= 10;
}
// 这里还没看明白
return x == reversed || x == reversed / 10;
}
}
解法三:Java流氓写法(调用api)(也是评论区大佬写的)
这个reverse()用的就很牛
public boolean isPalindrome(int x) {
return new StringBuilder(String.valueOf(x)).reverse().toString().equals(String.valueOf(x));
}
七、 删除有序数组中的重复项(26.)
解法一:直接抄solution,加上自己的理解默写
class Solution {
public int removeDuplicates(int[] nums) {
int len = 1;
for (int i = 0; i<nums.length-1; i++){
if(nums[i] != nums[i+1]){
nums[len] = nums[i+1];
len ++;
}
}
return len;
}
}
八、 移除元素(27.)
解法一:暴力解法
class Solution {
public int removeElement(int[] nums, int val) {
int a = 0;
for(int i = 0;i < nums.length;i++){
if(nums[i] != val){
nums[a] = nums[i];
a++;
}
}
return a;
}
}
解法二:大佬解法,fast slow指针,本质思想和俺的差不多
class Solution {
public int removeElement(int[] nums, int val) {
int fast = 0;
int slow = 0;
while(fast != nums.length){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
}
解法三:大佬解法,一个正向指针一个反向
class Solution {
public int removeElement(int[] nums, int val) {
// 对n的取值,要小心是length还是length-1
int n = nums.length;
int i = 0;
while(i < n){
if(nums[i] == val){
nums[i] = nums[n-1];
n--;
}else{
i++;
}
}
return n;
}
}
九、 加一(66.)
方法一:抄的大佬的解法
很少用到这种自定义方法,要背过这个!!
class Solution {
public int[] plusOne(int[] digits) {
return plusOneAtIndex(digits,digits.length - 1);
}
private int[] plusOneAtIndex(int[] digits,int index){
// 考虑[9]的情况 要扩展。
if(index < 0){
int[] ans = new int[digits.length + 1];
ans[0] = 1;
return ans;
}
// 如果这个位置<9即可直接加一,返回值就行
if(digits[index] < 9){
digits[index] ++;
return digits;
}
// 否则的话这个位置赋值0
digits[index] = 0;
// 这里相当于循环了,重复代值
return plusOneAtIndex(digits, index - 1);
}
}