leetcode两数之和暴力法的基础回顾

博主作为一名Java初学者,决定先从最简单直接的方法做起,并从中加强基础,之后再用其他更简单的方法。

暴力法

遍历每个元素 x,并查找是否存在一个值y,满足与 y=target - x。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] a = new int[2];
        for(int i=0;i<nums.length;i++){
            for(int j= i+1;j<nums.length;j++){
                if(nums[i]+nums[j]==target){
                    a[0]=i;
                    a[1]=j;
                }
            }
        }
        return a;
    }
}

时间复杂度为 O(n^2),空间复杂度:O(1)

基础回顾

Q0 :为什么数组要从 0 开始编号,而不是从 1 开始?

 我们拿一个长度为 10 的 int 类型的数组 int[] a = new int[10] 来举例。在我画的这个图中,计算机给数组 a[10],分配了一块连续内存空间 1000~1039,其中,内存块的首地址为 base_address = 1000。
数组
当计算机需要随机访问数组中的某个元素时,它会首先通过下面的寻址公式,计算出该元素存储的内存地址:

a[i]_address = base_address + i * data_type_size

 从数组存储的内存模型上来看,“下标”最确切的定义应该是“偏移(offset)”,a[0] 就是偏移为 0 的位置,也就是首地址,a[i] 就表示偏移 i 个 type_size 的位置。
 但是,如果数组从 1 开始计数,那我们计算数组元素 a[k] 的内存地址就会变为:

a[i]_address = base_address + (i-1) * data_type_size

 为了减少一次减法操作,则从 0 开始。

 数组和链表的区别,很多人都回答说,“链表适合插入、删除,时间复杂度 O(1);数组适合查找,查找时间复杂度为O(1)”。实际上,这种表述是不准确的。数组是适合查找操作,但是查找的时间复杂度并不为O(1)。即便是排好序的数组,你用二分查找,时间复杂度也是 O(logn)。所以,正确的表述应该是,数组支持随机访问,根据下标随机访问的时间复杂度为 O(1) 。

两数之和暴力法代码中数组的创建

int[] a = new int[2];

Q1 :Java在声明一个数组的过程中,初始化方式有几种,是如何分配内存的?

  • 静态初始化:由程序员指定初始值,由系统决定长度(int[] a = {1,2,3})
  • 动态初始化:由系统指定初始值,由程序员决定长度(int[] a = new int[3];)

动态初始化时系统赋值

类型初始值
整型(byte,short,int和long)0
浮点型(float,double)0.0
字符型(char)‘\u0000’(Unicode字符,相当于一个空格)
布尔型(boolean)false
引用类型(类,接口,和数组)null

PS:Java数组本身是没有办法被程序引用的,它需要赋值给一个变量,该变量称为数组变量,所以在初始化时,数组变量不一定要初始化,需要初始化的是数组本身,栈内存中的数组变量相当于一个指针,只需要指向堆内存中数组首地址即可。

A1: 数组在初始化过程中,有静态和动态两种初始化方式。两者区别在于静态由由程序员指定初始值,由系统决定长度;动态由系统指定初始值,由程序员决定长度。然后系统根长度在堆内存中寻找一块大小符合的连续内存块分配给数组,并根据数组类型初始化每个数组元素的值,初始化完之后,数组长度不可改变。

Q2 :什么是引用变量和引用对象,他们之间有什么联系?

A2: 首先我们先理清楚变量和对象之间的关系,所有的基础类型和引用类型变量都是存储在自己的方法栈区中的,而对象(包括数组、普通java对象)总是存储在堆内存中的,而所谓的引用是指将方法栈区中的变量指向堆内存中的对象,在程序中通过引用变量访问属性时,就会映射到变量指向的对象,使该对象变成引用对象。

Q3 : 你知道基本类型数组和引用类型数组之间,在初始化时内存分配机制有什么区别?
A3: 对于基础类型数组而言,它的元素就是一个固定的值,而对于引用类型数组而言,他的数组元素是一个引用类型变量,可以指向任何有效的内存,即你的引用类型是A,那么A对象数组的元素也需要指向一个A对象。所以在两种类型初始化时,还需为引用类型数组元素额外初始化另外一块内存,再把元素变量指向该内存地址。

Q4 : Java变量一定要初始化吗?
A4: 不一定。Java数组变量是引用数据类型变量,它并不是数组对象本身,只要让数组变量指向有效的数组对象,即可使用该数组变量。对数组执行初始化,并不是对数组变量进行初始化,而是对数组对象进行初始化——也就是为该数组对象分配一块连续的内存空间,这块连续的内存空间就是数组的长度。

Q5 : 基本类型变量都放在栈内存中?
A5: 错。应该这样说:所有局部变量都放在栈内存里保存的,不管其是基本类型的变量,还是引用类型变量,都是存储在各自的方法栈区中;但是引用类型变量所引用的对象(包括数组、普通java对象)则总是存储在堆内存中。

Q6 :引用变量何时只是栈内存中的变量本身,何时又变为引用实例的java对象?
A6: 引用变量本质上只是一个指针,只要程序通过引用变量访问属性,或者通过引用变量来调用方法,该引用变量将会由他所引用的对象代替。




参考文章:

https://blog.csdn.net/A1585570507/article/details/81805722
https://blog.csdn.net/weixin_33893979/article/details/114451184

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值