2023-02-26-JAVA刷题账目表
目录
待处理
周赛 6242
class Main{
public static void main(String[] args) {
Solution s = new Solution();
}
}
刷题中常用的Java方法
常见的数据类型
// 1. char 和String
// char s1="n";错误,char需要单引号
// char s1='nl';错误,char是一个字符
char s1='n';正确
// String s2='asdasd'; 错误,string 是双引号
String s2="asdasdasd";正确
// 2. long型
/*
系统不会自动将99999999999999当做long处理,而是当做int处理,而本身99999999999999超出int范围,故赋值失败
*/
//long num1=99999999999999;
/*
如果希望系统将99999999999999当做long处理,则需要在常量值后面添加l或L后缀
*/
long num1=99999999999999L;
// 3. float型
如果希望系统将1.5当做float处理,则需要在常量值后添加f或F后缀
float f2=1.5f;
常见的转义字符
| 转义字符 | 说明 |
|---|---|
| \b | 退格符 |
| \n | 换行符 |
| \r | 回车符 |
| \t | 制表符 |
| \” | 双引号 |
| \‘ | 单引号 |
自增操作i++
//格式1:运算符在操作数左边
/*
先将i自增1,然后赋值给j
*/
int i = 10;
int j = ++i;
System.out.println("i=" + i + "\tj=" + j);//i=11 j=11
//格式2:运算符在操作数右边
/*
现将i本身的值取出来放在操作数栈中,然后i自增1,再用操作数栈中的10赋值给j
*/
int i = 10;
int j = i++;
System.out.println("i=" + i + "\tj=" + j);//i=11 j=10
//格式3:混合运算
int i = 10;
int j = (i++) + (++i) * (i++);//j=10+12*12
System.out.println("i=" + i + "\tj=" + j);//i=13,j=154
创建string
//方式一:通过字符串常量的方式
String str1 = "joshua317";
//方式二:通过new一个对象方式创建
String str2 = new String("joshua317");
数组操作
创建int[] nums
//创建int[] nums
int[] nums = {1,3,5,2,5,1,2,3,4,5,7};
元素插入数组操作---add
public class Solution {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(0);//插入第一个元素
list.add(1);
System.out.println(list);//打印list数组
System.out.println(list);
}
}
System.arraycopy函数
//System.arraycopy(src, srcPos, dest, destPos, length);
public class Solution {
public static void main(String[] args) {
// 源数组
int[] src = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 目标数组
int[] dest = new int[10];
System.out.println("cope前:" + Arrays.toString(dest));//cope前:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
// copy(src, 2, dest, 5, 4);
System.arraycopy(src, 2, dest, 5, 4);
System.out.println("cope后:" + Arrays.toString(dest));//cope后:[0, 0, 0, 0, 0, 3, 4, 5, 6, 0]
}
}
一些稀奇古怪的省略
for(;;)
/*while(true) 和for(;;)是一样的
for(;;)
即不设初值,不判断条件,循环变量不增值.
无终止的循环。
那个程序会死循环
可以在循环中添加一个语句来说明这个问题*/
for(;;){
System.out.println("aa");
}
//会一直输出 字符串 aa
a&=b
“&=”是JavaScript赋值运算符,意思是将左边变量与右操作数的值按位与。如,a&=b,相当于a=a&b。等号“=”就是赋值用的。而&是JavaScript的位运算符,是按位与的意思,
就是当两个操作数的相应位都为1时,该位的结果为1,否则为0。
? :
条件运算符( ? : )也称为 “三元运算符”或“三目运算符”。语法形式:布尔表达式 ? 表达式1 :表达式2。
运算过程:如果布尔表达式的值为 true ,则返回 表达式1的值,否则返回 表达式2 的值。
数组:
2022-11-19----
二分法
E367
class Solution {
public boolean isPerfectSquare(int num) {
int left=0;
int right=num;
while (left<right){
int mid=left+((right-left)>>1);
long square=(long)mid *mid;
if (square<num){
left=mid+1;
}else if (square>num){
right=mid-1;
}else {
return true;
}
}
if (left*left==num){
return true;
}else {
return false;
}
// return false;
}
}
// E35
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while(left<=right){
int mid=((right-left)>>1)+left;
if(target==nums[mid]){
return mid;
} else if (nums[mid]<target) {
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
}
// M704;
class Solution {
public int search(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while(left<right){
int middle=left+((right-left)>>1);
if(nums[middle]<target){
left=middle+1;
}else if(nums[middle]==target){
right=middle;
}else{
right=middle-1;
}
}
if(nums[left]==target){
return left;
}else{
return -1;
}
}
}
package com.sue.M34;
/**
* @author Anthony
* @create 2022-11-21 17:59
*/
class Solution {
public int[] searchRange(int[] nums, int target) {
int l = nums.length;
if (l == 0) {
return new int[]{-1, -1};
}
int firstPosition = findFirstPosition(nums, target);
if (firstPosition == -1) {
return new int[]{-1, -1};
}
int lastPosition = findLastPosition(nums, target);
return new int[]{firstPosition, lastPosition};
}
private int findFirstPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int middle = left + ((right - left) >> 1);
/*
1先小于 left=middle+1
2等于时,middle=left
3小于时,right=middle-1
*/
if (nums[middle] < target) {
left = middle + 1;
} else if (nums[middle] == target) {
right = middle;
} else {
right = middle - 1;
}
}
/*循环完之后,left可能落在target,也可能 left > right都没找到 所以返回-1
*/
if (nums[left] == target) {
return left;
} else {
return -1;
}
}
private int findLastPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int middle = ((left + right +1) >> 1);//向上取整的精妙之处需要体会
/*
1先小于 left=middle+1
2等于时,middle=left
3小于时,right=middle-1
*/
if (nums[middle] < target) {
left = middle + 1;
} else if (nums[middle] == target) {
left = middle;
} else {
right = middle - 1;
}
}
return left;
}
}
class Main{
public static void main(String[] args) {
int []nums = {5,7,7,8,8,10};
int target = 8;
Solution s = new Solution();
int[] res = s.searchRange(nums, target);
// System.out.println(res);
for(int a:res)System.out.println(a);//数组输出的格式for
}
}
E69 可用二分法再做一遍
二分法搜索插入位置
/*
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
*/
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0,right=nums.length;
while(left<right){
int mid=(right-left)/2+left;
if(nums[mid]==target){
return mid;
}else if(nums[mid]<target){
left=mid+1;
}else{
right=mid;
}
}
return left;
}
}
27.移除元素
//E27
class Solution {
public int removeElement(int[] nums, int val) {
int l = nums.length;
int left = 0;
for (int right = 0; right < l; right++) {
if (nums[right] != val) {
nums[left] = nums[right];
left++;
}
}
return left;
}
}
class Solution1{
/*
双指针
*/
public int removeElement(int[] nums, int val) {
int left=0;
int right=nums.length-1;
while (left<=right){
if (nums[left]==val){
nums[left]= nums[right];
right--;
}else {
left++;
}
}
return left;
}
}
-
26.删除排序数组中的重复项 class Solution1{ public int removeDuplicates(int[] nums) { int l=nums.length; int q=0; for (int p=1;p<l;){ if (nums[p]==nums[q]){ p++; }else { nums[q+1]=nums[p]; q++; p++; } } return q+1; } }283.移动零 class Solution { // public void moveZeroes(int[] nums) { // if (nums==null){ // return; // } // int j=0; // for (int i=0;i<nums.length;i++){ // if (nums[i]!=0){ // int temp=nums[i]; // nums[i]=nums[j]; // nums[j++]=temp; // } // } // } public void moveZeroes(int[] nums) { if (nums==null){ return; } int j=0; for (int i=0;i<nums.length;i++){ if (nums[i]!=0){ if (i>j){ nums[j]=nums[i]; nums[i]=0; } j++; } } } }//844.比较含退格的字符串//977.有序数组的平方
59.螺旋矩阵II
54.螺旋矩阵
剑指Offer 29.顺时针打印矩阵
滑动窗口
//209.长度最小的子数组
class Solution{
public int minSubArrayLen(int target, int[] nums) {
int n= nums.length;
if (n==0){
return 0;
}
int ans=Integer.MAX_VALUE;
int start=0;
int end=0;
int sum=0;
while (end<n){
sum=sum+nums[end];
while (sum>=target){
ans=Math.min(end-start+1,ans);//更新ans 因为sum还是>=target,且start++了。
sum=sum-nums[start];
start++;
}
end++;
}
return ans==Integer.MAX_VALUE?0:ans;//针对的是target=11 nums=[1,1,1,1]
}
}
//904.水果成篮(opens new window)
class Solution {
public int totalFruit(int[] fruits) {
int n=fruits.length;
HashMap<Integer, Integer> cnt = new HashMap<>();
int left=0;
int ans=0;
for (int right =0;right<n;++right){
cnt.put(fruits[right],cnt.getOrDefault(fruits[right],0)+1);
while (cnt.size()>2){
cnt.put(fruits[left],cnt.get(fruits[left])-1);
if (cnt.get(fruits[left])==0){
cnt.remove((fruits[left]));
}
++left;
}
ans=Math.max(ans,right-left+1);
}
return ans;
}
}
//76.最小覆盖子串
很难
双指针
/*
M713
*/
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
if (k <= 1)
return 0;
int n = nums.length, ans = 0, prod = 1, left = 0;
for (int right = 0; right < n; ++right) {
prod *= nums[right];
while (prod >= k) // 不满足要求,把左端点值除掉,然后left++,while继续判断
prod /= nums[left++];
ans += right - left + 1;//此时的子数组个数为right-left+1,如right=left时,为1
}
return ans;
}
}
杂项
//977.有序数组的平方
class Solution {
public int[] sortedSquares(int[] nums) {
int [] ans=new int[nums.length];
for (int i=0;i<ans.length ;i++ ) {
ans[i]=nums[i]*nums[i];
}
Arrays.sort(ans);
return ans;
}
}
链表
哈希表
Map接口的方法
// 1.hashMap的创建
Map<Integer, Integer> map = new HashMap<Integer, Integer>();//<1,2>位置1、2可以是String、List、Integer、
new HashMap<Integer, String>() {{
put("0","成功");
}};
// 2.添加操作
void put(key,value);//如果key不在map中,则会新添加
void putAll(Map,map);//将另一个map中的键值对添加到当前Map集合中,如果key相同,则会覆盖原有value
// 3.删除操作
void clear();//清空当前map集合
Object remove(Object key)//根据指定的key从当前map中删除一对映射关系
// 4.查询操作
Object get(Object key)//根据指定的key从当前map中查找其对应的value
boolean containsKey(Object key)//判断在当前map中是否存在指定的key
boolean containsValue(Object value)//判断在当前map中是否存在指定的value
Object getOrDefault(Object key, V defaultValue)//意思就是当Map集合中有这个key时,就使用这个key对应的value值,如果没有就使用默认值defaultValue
boolean isEmpty()//判断当前map是否为空
// 5.其他操作
int size()//获取当前map中(key,value)的键值对数。
字符串
双指针法
栈与队列
//E844
//M11
class Solution {
public int maxArea(int[] height) {
int left=0;
int right=height.length-1;
int ans=0;
while (left<right){
// int area = (right - left) * Math.min(height[left], height[right]);
int area=(right-left)*Math.min(height[left],height[right]);
ans=Math.max(ans,area);
if (height[left]<height[right]){
left++;
}else {
right--;
}
}
return ans;
}
}
二叉树
回溯&递归
贪心算法
动态规划
斐波那契数列(滚动数组)
斐波那契数的边界条件是 F(0)=0 和 F(1)=1。当 n>1 时,每一项的和都等于前两项的和,因此有如下递推关系:
F(n)=F(n−1)+F(n−2)
由于斐波那契数存在递推关系,因此可以使用动态规划求解。动态规划的状态转移方程即为上述递推关系,边界条件为 F(0)和 F(1)。
根据状态转移方程和边界条件,可以得到时间复杂度和空间复杂度都是 O(n)的实现。由于 F(n) 只和 F(n−1) 与 F(n−2)有关,因此可以使用「滚动数组思想」把空间复杂度优化成 O(1)。如下的代码中给出的就是这种实现。
/*
边界条件是 F(0)=0 和 F(1)=1
递推关系是fn=fn-1+fn-2
根据状态转移方程和边界条件,可以得到时间复杂度和空间复杂度都是
O(n) 的实现。由于 F(n) 只和 F(n−1)
与 F(n−2)有关,因此可以使用「滚动数组思想」把空间复杂度优化成
O(1)。如下的代码中给出的就是这种实现。
*/
//E509
class Solution {
public int fib(int n) {
if (n<2) {
return n;
}
int p=0,q=0,r=1;
for (int i=2;i<=n ;i++ ) {
p=q;//0
q=r;//1
r=p+q;//1
}
return r;
}
}
//E746
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int[] dp = new int[n + 1];
dp[0] = dp[1] = 0;
for (int i = 2; i <= n; i++) {
dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
return dp[n];
}
}
//优化版 使用滚动数组的思想,将空间复杂度优化到 O(1)。
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int prev = 0, curr = 0;
for (int i = 2; i <= n; i++) {
int next = Math.min(curr + cost[i - 1], prev + cost[i - 2]);
prev = curr;
curr = next;
}
return curr;
}
}
浙公网安备 33010602011771号