数据结构与算法(上) Datawhale组队学习——数组

引言

学习了JAVA的基础知识以后,这是本人第一次接触数据结构与算法的知识,为了更高效以及自律的学习,我加入了Datawhale学习小组


Task01------数组


理论部分:


一、理解数组的存储与分类。


1.数组的定义

数组是把具有相同类型的若干元素按无序的形式组织起来的一种形式
例如:

  • 基本数据类型数组 int[] array={3,1,4,1,5,9};
  • 对象数组 Object[] obj_array={Object obj1,Object obj2,Object obj3};

当然,还有二维,三维甚至更高维的数组,但是在定义上有相似点,暂不赘述

2.数组的储存
i>数组储存的特点
  • 数组元素在内存中按顺序连续存储。

  • 数组的存储分配按照行或列进行。

    例: 对于二维数组a[m][n]
    按行优先存储的线性序列为:
    a11,a12,…,a1n , a21,a22,…,a2n ,……,am1,am2,…,amn
    而按列优先存储的线性序列为:
    a11,a21,…,am1 , a12,a22,…,am2 ,……,a1n,a2n,…,amn
    
  • 数组名表示该数组的首地址,是常量。

ii>java中数组的储存原理

对于int[] array=new int[5];
1.array指向的是array[0]的地址,储存在栈内存中
2.array[i] 按行优先储存在堆内存中
绘制不易

iii>数组元素地址的计算

一维数组a[n]
图片来源Datawhale
二维数组a[m][n]
图片来源Datawhale
三维及以上的地址同理类推即可


二、实现动态数组,该数组能够根据需要修改数组的长度


1.java的集合类ArrayList

用集合类感觉有些作弊的嫌疑,索性直接写一个。

2.构造一个动态数组类(以int型为例)
i>基本框架(只完成部分功能)

绘制不易

ii>代码实现

构造方法

class DArray<T>{
	private T[] _array=null;
	private int size;
	//给数组初始化容量
	DArray(int capacity){	
		_array=(T[])new Object[capacity];
		size=0;
	}
	DArray(){
		this(10);
	}
}

私有方法

//获得当前容量
private int getCapacity() {
		return this._array.length;
	}
/**
*使数组得以动态改变大小的方法
*@param new_capacity:新数组的长度
*/
private void reCapacity(int new_capacity) {
	//需要强制转换接受泛型数组
	T[] new_array=(T[])new Object[new_capacity]; 
	for(int i=0;i<this.size;i++)
		new_array[i]=this._array[i];
	this._array=new_array;
}

对外暴露的公共方法(部分)

//按下标获取动态数组元素
public T get(int index) {
	return this._array[index];
}
//获取数组实际长度
public int getSize() {
	return size;
}
/**
*向指定位置添加元素,元素依次后移
*@param index:添加元素的位置
*@param value:添加的元素
*/
public void add(int index,T value) {
	//判断是否需要扩容
	if(this.size==this._array.length)
		this.reCapacity(this.getCapacity()*2);
	
	if(index>=0 && index<=this.size) { //偷个懒,只执行合法的下标插入
		for(int i=size;i>index;i--) 
			_array[i]=_array[i-1];
		_array[index]=value;
		this.size++;
	}
}
//向末尾添加元素
public void add(T value) {
	this.add(this.size, value);
}
//删除指定位置元素,后方元素依次前移
public void remove(int index) {
	if(index>=0 && index<=this.size) {
		for(int i=index;i<this.size;i++)
			this._array[i]=this._array[i+1];
		this.size--;
		this._array[size]=null;
	}
	//判断是否需要缩小容量(这里以1/2为临界)
	if(this.size<this._array.length/2)
		this.reCapacity(this.getCapacity()/2);
}

练习部分


一、利用动态数组解决数据存放问题

1.要求

编写一段代码,要求输入一个整数N,用动态数组A来存放2~N之间所有5或7的倍数,输出该数组。

示例:

输入:
N = 100 

输出:
5 7 10 14 15 20 21 25 28 30 35 40 42 45 49 50 55 56 60 63 65 70 75 77 80 84 85 90 91 95 98 100
2.分析

(虽然简单,还是走个过场比较好)
对于输入的上限N,须遍历[2,N]所有数,将符合条件的数存入DArray,最后输出DArray中所有元素即可

3.代码实现
import java.util,Scanner;
public class Text {
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int N,index=0;
		N=in.nextInt();
		//此动态数组的代码在上方,此处直接引用
		DArray<Integer> da=new DArray<Integer>();
		for(int i=2;i<=N;i++) 
			if(i%5==0 || i%7==0) {
				da.add(i);
				System.out.print(da.get(index++)+" ");
			}
	}
}

二、托普利茨矩阵问题(LeetCode第766题)

1.要求

如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。

给定一个M x N的矩阵,当且仅当它是托普利茨矩阵时返回True。
示例:

输入:
matrix = [
          [1,2,3,4],
          [5,1,2,3],
          [9,5,1,2]
         ]

输出: True
2.分析

图片很糊别介意
判断矩阵是否为托普利茨矩阵
== 判断所有蓝线上的元素是否相同
== 判断每一个 matrix [i] [j]==matrix [i+1] [j+1]?
其中末行,末列元素 (即红线元素) 跳过判断

3.代码实现
public class Text {
	public static void main(String[] args) {
		boolean flag=true;
		int[][] matrix={
						{1,2,3,4},
						{5,1,2,3},
						{9,5,1,2}
					   };
		//遍历除了末行,末列的每个元素
		for(int i=0;i<matrix.length-1;i++)
			for(int j=0;j<matrix[0].length-1;j++)
				if(!(matrix[i][j]==matrix[i+1][j+1]))
					flag=false;
		System.out.print(flag);
	}
}

三、三数之和(LeetCode第15题)

1.要求

给定一个包含 n 个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a + b + c = 0?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
 [-1, 0, 1],
 [-1, -1, 2]
]
2.分析
  • 当数组乱序时,没有一定的规律去寻找目标a,b,c,将数组排序后问题会简化很多,升序后:[-4,-1,-1,0,1,2]
  • 每次固定一个nums [i],在nums [i] 后方元素中寻找另外两个元素
  • 构造左右指针L=i+1, R=len-1,在 [L,R] 间寻找nums [L],nums [R]直到L>R
  • 由于题目要求不能重复,对nums [i],nums [L],nums [R]都必须有相应的去重措施
3.代码实现
class Solution {
    public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList();
        int len = nums.length;
        Arrays.sort(nums); // 排序(升序)
        for (int i = 0; i < len ; i++) {
        	// 升序数列,如果当前数字大于0,则三数之和一定大于0,所以结束循环
            if(nums[i] > 0) break; 
            if(i > 0 && nums[i] == nums[i-1]) continue; // 对a的去重
            int L = i+1;
            int R = len-1;
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                if(sum == 0){
                    result.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    while (L<R && nums[L] == nums[L+1]) 
                    	L++; // 对b去重
                    while (L<R && nums[R] == nums[R-1]) 
                    	R--; // 对c去重
                    L++;
                    R--;
                }
                else if (sum < 0) L++;
                else if (sum > 0) R--;
            }
        }        
        return result;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值