Java在迭代中使用全局变量重置

huangapple go评论57阅读模式
英文:

Java use global variable reset in iteration

问题

这种情况可能发生在单线程环境中是因为在第一个代码示例中,res 在每次递归调用 backTrace 后没有累积,因此它在每个递归层次中都被重置为0。这是因为在每次递归中,backTrace 返回了1或0,但这个返回值没有被添加到 res 中。

在第二个代码示例中,通过引入变量 a 来保存 backTrace 的返回值,并将其添加到 res 中,确保了递归的结果被累积。

在单线程环境中,如果不显式地将递归调用的结果累积到一个变量中,那么递归调用不会影响到外部的 res 变量,因此它会在每个递归层次中被重置。所以,为了正确地累积结果,你需要将递归的返回值添加到 res 中,这就是为什么第二个代码示例中的做法是正确的。

英文:

I have the code work with iteration in a single thread enviorment:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

class Solution {
	int res = 0;

	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String line;
		while ((line = in.readLine()) != null) {
			int n = Integer.parseInt(line);

			int ret = new Solution().totalNQueens(n);

			String out = String.valueOf(ret);

			System.out.print(out);
		}
	}

	public int totalNQueens(int n) {
		Set<Integer> columns = new HashSet<Integer>();
		Set<Integer> record1 = new HashSet<Integer>();
		Set<Integer> record2 = new HashSet<Integer>();
		backTrace(n, 0, columns, record1, record2);
		return res;
	}

	private int backTrace(int n, int row, Set<Integer> columns, Set<Integer> record1, Set<Integer> record2) {
		if (n == row) {
			return 1;
		}
		for (int i = 0; i < n; i++) {
			if (columns.contains(i)) {
				continue;
			}
			int check1 = row - i;
			if (record1.contains(check1)) {
				continue;
			}
			int check2 = row + i;
			if (record2.contains(check2)) {
				continue;
			}
			columns.add(i);
			record1.add(check1);
			record2.add(check2);
			System.out.println("res start:" + res);
			res = res + backTrace(n, row + 1, columns, record1, record2);
			System.out.println("res end:" + res);
			columns.remove(i);
			record1.remove(check1);
			record2.remove(check2);
		}
		return 0;
	}
}

the result of the code is below, and it seems the res reset when res = res + backTrace(n, row + 1, columns, record1, record2);

res start:0
res start:0
res end:0
res start:0
res start:0
res end:0
res end:0
res end:0
res start:0
res start:0
res start:0
res start:0
res end:1
res end:0
res end:0
res end:0
res start:0
res start:0
res start:0
res start:0

and when we change the code, let a new variable to save the result of backTrace, and it works fine.

package com.nbp.cdncp.vpe.api.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

class Solution {
	int res = 0;

	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String line;
		while ((line = in.readLine()) != null) {
			int n = Integer.parseInt(line);

			int ret = new Solution().totalNQueens(n);

			String out = String.valueOf(ret);

			System.out.print(out);
		}
	}

	public int totalNQueens(int n) {
		Set<Integer> columns = new HashSet<Integer>();
		Set<Integer> record1 = new HashSet<Integer>();
		Set<Integer> record2 = new HashSet<Integer>();
		backTrace(n, 0, columns, record1, record2);
		return res;
	}

	private int backTrace(int n, int row, Set<Integer> columns, Set<Integer> record1, Set<Integer> record2) {
		if (n == row) {
			return 1;
		}
		for (int i = 0; i < n; i++) {
			if (columns.contains(i)) {
				continue;
			}
			int check1 = row - i;
			if (record1.contains(check1)) {
				continue;
			}
			int check2 = row + i;
			if (record2.contains(check2)) {
				continue;
			}
			columns.add(i);
			record1.add(check1);
			record2.add(check2);
			System.out.println("res start:" + res);
			var a = backTrace(n, row + 1, columns, record1, record2);
			res += a;
			System.out.println("res end:" + res);
			columns.remove(i);
			record1.remove(check1);
			record2.remove(check2);
		}
		return 0;
	}
}

the result:

res start:0
res start:0
res end:0
res start:0
res start:0
res end:0
res end:0
res end:0
res start:0
res start:0
res start:0
res start:0
res end:1
res end:1
res end:1
res end:1
res start:1
res start:1
res start:1
res start:1
res end:2
res end:2
res end:2
res end:2
res start:2
res start:2
res start:2
res end:2
res end:2
res start:2
res end:2
res end:2
2

Why this happens in a single thread environment

答案1

得分: 1

以下是您要翻译的部分:

"The expression res + backTrace(n, row + 1, columns, record1, record2) is evaluated left to right. This means the value of res is read before calling backTrace, and doesn’t reflect the change to the value that happens within that method call.

If you reverse the order of arguments to backTrace(n, row + 1, columns, record1, record2) + res, this avoids the problem, however this may still make the code hard to understand. Most people expect addition to be commutative. This assumption is violated in code where evaluation of one of the operands affects the value of the other. It would be clearer to rewrite the method to avoid using the non-local variable res:

class Solution {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = in.readLine()) != null) {
            int n = Integer.parseInt(line);

            int ret = new Solution().totalNQueens(n);

            String out = String.valueOf(ret);

            System.out.print(out);
        }
    }

    public int totalNQueens(int n) {
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> record1 = new HashSet<Integer>();
        Set<Integer> record2 = new HashSet<Integer>();
        return backTrace(n, 0, columns, record1, record2);
    }

    private int backTrace(int n, int row, Set<Integer> columns, Set<Integer> record1, Set<Integer> record2) {
        if (n == row) {
            return 1;
        }
        int res = 0;
        for (int i = 0; i < n; i++) {
            if (columns.contains(i)) {
                continue;
            }
            int check1 = row - i;
            if (record1.contains(check1)) {
                continue;
            }
            int check2 = row + i;
            if (record2.contains(check2)) {
                continue;
            }
            columns.add(i);
            record1.add(check1);
            record2.add(check2);
            System.out.println("res start:" + res);
            res += backTrace(n, row + 1, columns, record1, record2);
            System.out.println("res end:" + res);
            columns.remove(i);
            record1.remove(check1);
            record2.remove(check2);
        }
        return res;
    }
}
英文:

The expression res + backTrace(n, row + 1, columns, record1, record2) is evaluated left to right. This means the value of res is read before calling backTrace, and doesn’t reflect the change to the value that happens within that method call.

If you reverse the order of arguments to backTrace(n, row + 1, columns, record1, record2) + res, this avoids the problem, however this may still make the code hard to understand. Most people expect addition to be commutative. This assumption is violated in code where evaluation of one of the operands affects the value of the other. It would be clearer to rewrite the method to avoid using the non-local variable res:

class Solution {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = in.readLine()) != null) {
            int n = Integer.parseInt(line);

            int ret = new Solution().totalNQueens(n);

            String out = String.valueOf(ret);

            System.out.print(out);
        }
    }

    public int totalNQueens(int n) {
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> record1 = new HashSet<Integer>();
        Set<Integer> record2 = new HashSet<Integer>();
        return backTrace(n, 0, columns, record1, record2);
    }

    private int backTrace(int n, int row, Set<Integer> columns, Set<Integer> record1, Set<Integer> record2) {
        if (n == row) {
            return 1;
        }
        int res = 0;
        for (int i = 0; i < n; i++) {
            if (columns.contains(i)) {
                continue;
            }
            int check1 = row - i;
            if (record1.contains(check1)) {
                continue;
            }
            int check2 = row + i;
            if (record2.contains(check2)) {
                continue;
            }
            columns.add(i);
            record1.add(check1);
            record2.add(check2);
            System.out.println("res start:" + res);
            res += backTrace(n, row + 1, columns, record1, record2);
            System.out.println("res end:" + res);
            columns.remove(i);
            record1.remove(check1);
            record2.remove(check2);
        }
        return res;
    }
}

huangapple
  • 本文由 发表于 2023年5月18日 11:20:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76277514.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定