BST中第K个最小元素的静态和非静态差异

时间:2018-02-09 19:38:09

标签: java static non-static

在这个问题中,如果我在第二行count中创建static变量,如图所示,kthSmallest()方法会计算错误的答案。如果变量变为非static,则计算正确的答案。非静态方法可以使用静态变量,为什么会有差异呢?

class Solution {
    public static int count = 0;
    public int res = 0;

    public int kthSmallest(TreeNode root, int k) {
        inorder(root,k);
        return res;
    }

    public void inorder(TreeNode root, int k) {
        if (root == null) return;
        inorder(root.left,k);
        count++;
        if (count == k) {
            res = root.val;
            return;
        }
        inorder(root.right,k);
    }
}

1 个答案:

答案 0 :(得分:0)

我认为没有理由为count方法的单次运行的结果会因staticcount而受影响,但是如果您执行多个运行,无论是顺序还是并行,您肯定会遇到问题。 static Solution表示类Solution的每个实例都共享该变量,您将其初始化为零,然后仅递增。无论是在count的相同还是不同的实例上,该方法的第二次运行将继续前一次运行所留下的count值。

通过确保static的每个实例都有自己的Solution变量,使count非 - kthSmallest()部分解决了该问题。使用同一实例执行多个kthSmallest()计算仍然存在问题,但是您可以为每个实例执行一次正确的运行。如果你通过一些自动判断测试这个,那么它确实为每个测试用例创建一个单独的实例是合理的。

但即使这不是完整的解决方案。每个实例最多只能运行一次,如果尝试使用同一个实例执行两次并发运行,您甚至无法确保获得该运行。这里的根本问题是您使用实例(或类)变量来保存特定于class Solution { // no class or instance variables at all public int kthSmallest(TreeNode root, int k) { // int[1] is the simplest mutable container for an int int[] result = new int[1]; inorder(root, k, result); return result[0]; } // does not need to be public: // returns the number of nodes traversed (not necessarily the whole subtree) int inorder(TreeNode root, int k, int[] result) { if (root == null) { return 0; } else { // nodes traversed in the subtree, plus one for the present node int count = inorder(root.left, k, result) + 1; if (count == k) { result[0] = root.val; } else { count += inorder(root.right, k, result); } return count; } } } 方法的单个运行的状态。

您应该使用该方法的局部变量,如果需要,通过方法参数和/或返回值传递给其他方法。例如:

Public Class Form1
    Private clients As DataTable

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'Create a new instance of a datatable
        clients = New DataTable("Clients")

        'Add your columns
        clients.Columns.AddRange({
            New DataColumn("client_id", GetType(Integer)) With {.AutoIncrement = True},
            New DataColumn("forename") With {.MaxLength = 15},
            New DataColumn("surname") With {.MaxLength = 15},
            New DataColumn("address1") With {.MaxLength = 30},
            New DataColumn("postcode") With {.MaxLength = 9},
            New DataColumn("rdate", GetType(DateTime)),
            New DataColumn("notes") With {.MaxLength = 1000},
            New DataColumn("home_insurance", GetType(Boolean)),
            New DataColumn("mortgage", GetType(Boolean)),
            New DataColumn("home_mover", GetType(Boolean)),
            New DataColumn("first_time_buyer", GetType(Boolean)),
            New DataColumn("buy_let", GetType(Boolean)),
            New DataColumn("life_insurance", GetType(Boolean)),
            New DataColumn("critical_illness", GetType(Boolean)),
            New DataColumn("income_protection", GetType(Boolean))
            })

        'Check if the file exists to deserialize the data
        If IO.File.Exists("D:\temp\clients.xml") Then
            clients.ReadXml("D:\temp\clients.xml")
        End If

        'Bind the controls
        BindingSource1.DataSource = clients
        DataGridView1.DataSource = clients
        BindingNavigator1.BindingSource = BindingSource1
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Try
            'Create a file if it does not exist
            If Not IO.File.Exists("D:\temp\clients.xml") Then
                IO.File.Create("D:\temp\clients.xml")
            End If

            'Serialize the data
            clients.WriteXml("D:\temp\clients.xml", XmlWriteMode.WriteSchema)
        Catch ex As Exception
            'Display any errors
            MessageBox.Show("There was an error serializing the data.", "Error", MessageBoxButtons.OK)
            Console.WriteLine(ex.Message)
        End Try
    End Sub

    Private Sub ToolStripButtonSearch_Click(sender As Object, e As EventArgs) Handles ToolStripButtonSearch.Click
        If String.IsNullOrWhiteSpace(ToolStripTextBoxSearch.Text) Then
            'If there is no String, remove the filter
            BindingSource1.RemoveFilter()
        Else
            'If there is 
            BindingSource1.Filter =
                $"forename = '{ToolStripTextBoxSearch.Text}' 
                OR surname = '{ToolStripTextBoxSearch.Text}'
                OR CONVERT(client_id, 'System.String') = '{ToolStripTextBoxSearch.Text}'"
        End If
    End Sub

End Class