前言:
在力扣上提交代码,发现用static定义变量,和不用static修饰变量,虽然每次运行的结果都一样,但是提交的结果却有通过与不通过两种情况。
测试题目:组合(力扣)dfs + 回溯 + 剪枝 JAVA
static修饰全局变量:
代码:
class Solution {
public static List<List<Integer>> nums = new ArrayList<>();
public static List<Integer> num = new ArrayList<>();
public static List<List<Integer>> combine(int n, int k) {
dfs(1, n, k);
return nums;
}
public static void dfs(int i, int n, int k) {
if(num.size() + n - i + 1 < k) return;//剪枝
if(num.size() == k) {
nums.add(new ArrayList<Integer>(num));
return;
}//重要的事情最先做
num.add(i);//装
dfs(i + 1, n, k);
num.remove(num.size() - 1);//回溯(不装)
dfs(i + 1, n, k);
}
}
不用static修饰:
代码:
class Solution {
List<List<Integer>> nums = new ArrayList<>();
List<Integer> num = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(1, n, k);
return nums;
}
public void dfs(int i, int n, int k) {
if(num.size() + n - i + 1 < k) return;//剪枝
if(num.size() == k) {
nums.add(new ArrayList<Integer>(num));
return;
}//重要的事情最先做
num.add(i);//装
dfs(i + 1, n, k);
num.remove(num.size() - 1);//回溯(不装)
dfs(i + 1, n, k);
}
}
值得注意的是,上述两个代码算法完全一样,不同点出在,全局变量是否用static修饰
抱着些许疑惑我写了一个程序分别测试了两个代码:
代码:
import java.util.*;
public class Main {
public static void main(String args[]) {
int i[] = {4, 1};
int k[] = {2, 1};
for(int x = 0; x < 2; x ++) {
Solution s = new Solution();
Solution_promax ss = new Solution_promax();
System.out.println(s.combine(i[x], k[x]));
System.out.println("\033[36m");
System.out.println(ss.combine(i[x], k[x]));
System.out.println("\033[0m");
}
// Solution_promax ss = new Solution_promax();
// System.out.println(ss.combine(4, 2));
//
// Solution_promax ss1 = new Solution_promax();
// System.out.println(ss1.combine(4, 2));
//
// System.out.println(ss.combine(4, 2));
}
}
class Solution {
List<List<Integer>> nums = new ArrayList<>();
List<Integer> num = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(1, n, k);
return nums;
}
public void dfs(int i, int n, int k) {
if(num.size() + n - i + 1 < k) return;//剪枝
if(num.size() == k) {
nums.add(new ArrayList<Integer>(num));
return;
}//重要的事情最先做
num.add(i);//装
dfs(i + 1, n, k);
num.remove(num.size() - 1);//回溯(不装)
dfs(i + 1, n, k);
}
}
class Solution_promax {
public static List<List<Integer>> nums = new ArrayList<>();
public static List<Integer> num = new ArrayList<>();
public static List<List<Integer>> combine(int n, int k) {
dfs(1, n, k);
return nums;
}
public static void dfs(int i, int n, int k) {
if(num.size() + n - i + 1 < k) return;//剪枝
if(num.size() == k) {
nums.add(new ArrayList<Integer>(num));
return;
}//重要的事情最先做
num.add(i);//装
dfs(i + 1, n, k);
num.remove(num.size() - 1);//回溯(不装)
dfs(i + 1, n, k);
}
}
输出:
1.惊奇的发现用static修饰的变量,不会因为创建新的对象,而恢复初始化
2.不用static修饰的全局变量创建的新对象,内容会恢复初始化
而力扣测试一组代码,就是不断创建新对象,带入数据比对结果,而static修饰全局变量会导致数据叠加。这就是为什么我用static修饰全局变量无法通过的原因。
那么static修饰得全局变量,只需要每次调用函数人为初始化即可:
代码:
class Solution {
public static List<List<Integer>> nums = new ArrayList<>();
public static List<Integer> num = new ArrayList<>();
public static List<List<Integer>> combine(int n, int k) {
nums = new ArrayList<>();
num = new ArrayList<>();//初始化
dfs(1, n, k);
return nums;
}
public static void dfs(int i, int n, int k) {
if(num.size() + n - i + 1 < k) return;//剪枝
if(num.size() == k) {
nums.add(new ArrayList<Integer>(num));
return;
}//重要的事情最先做
num.add(i);//装
dfs(i + 1, n, k);
num.remove(num.size() - 1);//回溯(不装)
dfs(i + 1, n, k);
}
}
得出简略结论:
1、static目的:java中的static关键字主要用于内存管理。
2.静态变量可以被类的所有实例共享,因此静态变量可以作为实例之间的共享数据,增加实例之间的交互性。
3.如果类的所有实例都包含一个相同的常量属性,则可以把这个属性定义为静态常量类型,从而节省内存空间。