DAY1数组

  • 组队学习详情:https://github.com/datawhalechina/team-learning/blob/master/数据结构与算法(上)/学习任务.md
1. 数组定义
  • 数组是一种线性数据结构,用连续的存储空间存储相同类型数据
  • 线性表:数组、链表、队列、栈 非线性表:树、图
  • 连续的内存空间、相同的数据,所以数组可以随机访问;但对数组进行删除、插入时,为了保证数组的连续性,就要做大量的数据搬移工作
2. 数组与链表区别
  • 数组是顺序的存储结构,链表是链式的存储结构
  • 链表的插入删除元素相对数组较为简单,不需要移动元素,且较为容易实现长度扩充,但是寻找某个元素较为困难。
  • 数组插入数据和删除数据效率低,插入数据时,这个位置后面的数据在内存中都要向后移。删除数据时,这个数据后面的数据都要往前移动。
  • 随机读取效率很高。因为数组是连续的,知道每一个数据的内存地址,可以直接找到给地址的数据。
  • 在内存中,数组是一块连续的区域
3. 为什么数组要从 0 开始编号,而不是从 1 开始呢
  • 从偏移角度理解 a[0]
  • 为什么循环要写成for(int i = 0;i<3;i++)而不是for(int i = 0;i<=2;i++)? 留一个问题

练习部分

以下代码为C & python 版本

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

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

示例

输入:N=100

输入:
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

代码C语言:

#include <stdio.h>
#include <stdlib.h>

int main() {
    
    int n,i,length=0;
    int  *array;
    array=0;
    printf("input N:");
    scanf("%d",&n);

    for (i = 1; i <=n; i++)
    {
        if (!(i%5)||!(i%7))
        {
            if (!array){
                array = (int*)malloc(sizeof(int));
                length+=1;
                *array = i;
            }else{
                array = (int*)realloc(array,(length+1)*sizeof(int));
                length+=1;
                *(array+length-1) = i;
            }
        }
    }

    for ( i = 0; i < length; i++)
    {
       printf("%d ",*(array+i));
    }

    free(array);
    while(1);
    return 0;
}

python版本:

a = int(input("N="))
b = [None if a < 5 else i for i in range(5, a+1, 5)]  #  真  if 条件 else 。。   用i for i in range(根据已有列表,高效创建新列表的方式。) 速度比 for i in range 快
c = [None if a < 7 else i for i in range(7, a+1, 7)]
d = list(set(b+c))     #set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等
for i in d:
    print(i,end=" ")  #用空格隔开

java版本:

package array;
import java.util.Arrays;
import java.util.Scanner;
public class dynamic {
    public static void main(String[] args) {
        while (true) {
            System.out.print("是否运行程序Y/N:");
            Scanner YY = new Scanner(System.in);
            String S = YY.next();
            if(S.charAt(0)=='Y'){
                System.out.print("请输入一个数字:");
                Scanner in = new Scanner(System.in);
                int N = in.nextInt();
                int j = 0;
                int[] array1 = new int[5];
                for (int i = 2; i <= N; i++) {
                    if (i % 5 == 0 || i % 7 == 0) {
                        array1[j] = i;
                        j++;
                    }
                    if (j == array1.length)
                        array1 = Arrays.copyOf(array1, array1.length + 10);
                }
                for (int temp : array1) {
                    if (temp != 0)
                        System.out.print(temp + "\t");
                }
                System.out.println("");
            }
            else if(S.charAt(0)=='N') break;
            else
                System.out.println("请输入正确的字母");
            }
    }
}

2. 托普利茨矩阵问题

如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。
给定一个M x N的矩阵,当且仅当它是托普利茨矩阵时返回True。

示例:

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

解释:

在上述矩阵中, 其对角线为: “[9]”, “[5, 5]”, “[1, 1, 1]”, “[2, 2, 2]”, “[3, 3]”, “[4]”。 各条对角线上的所有元素均相同, 因此答案是True。

代码c语言:

#include <stdio.h>
#include <stdlib.h>
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b

int main() {
    
    int flag=0;
    int m,n,i,j=0,k=0,length=0;
    int  *array;
    array = (int*)malloc(sizeof(int));

    printf("Input Matrix:");
    printf("Input M:");
    scanf("%d",&m);

    printf("Input N:");
    scanf("%d",&n);


    for (i = 0; i <m*n; i++)
    {
        printf("current:%d ,total: %d Input data:",i+1,m*n);
        scanf("%d",(array+length));
        ++length;
        array = (int*)realloc(array,(length+1)*sizeof(int));


    }

    printf("Matrix:\r\n");//输出数组

    for ( i = 0; i < n; i++)
    {
        for ( j = i*m; j < (i+1)*m; j++)
        {
            printf("%d ",*(array+j));
        }
       printf("\r\n");
    }

    printf("----------------------------\r\n");

    for ( i = 0; i < n-1; i++)
    {
        for ( j = i*m; j < (i+1)*m-1; j++)
        {
            if (j+m+1<m*n)
            {
                printf("%d ",*(array+j));
                printf("compare to:%d \r\n",*(array+j+m+1));
                if (*(array+j)!=*(array+j+m+1))
                {
                    flag = 1;
                }
            }
        }
    }

    if (flag)printf("False");
    else printf("True");

    free(array);
    while(1);
    return 0;
}

python语言:

    #遍历数组,判断每一个元素和它右下方元素(行数和列数均加一)是否相等
#每一行最后一个元素以及最后一行元素无需比较(已经比较过了)
#所以遍历时,行数和列数都要减1

class Solution(object):
    def isMarix(matrix):
        for i in range(len(matrix) - 1):
            if not matrix[i][:-1] == matrix[i+1][1:]:      #使用列表的时候,如果你想区分x==[]和x==None两种情况的话, 此时if not x:将会出现问题:
                return False                              #使用if not x这种写法的前提是:必须清楚x等于None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()时对你的判断没有影响才行
            return True
3.三数之和

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

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

示例:

最后一题C太耗时,还没写出来,答案仅供参考

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

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
算法流程:
    特判,对于数组长度 n,如果数组为 null 或者数组长度小于 3,返回 []。
    对数组进行排序。
    遍历排序后数组:
        若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
        对于重复元素:跳过,避免出现重复解
        令左指针 L=i+1,右指针 R=n−1,当 L<R时,执行循环:
            当nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,RL,RL,R 移到下一位置,寻找新的解
            若和大于0,说明 nums[R] 太大,R 左移
            若和小于0,说明 nums[L] 太小,L 右移
            

---

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        # 存储结果列表
        res_list = []
        # 对nums列表进行排序,无返回值,排序直接改变nums顺序
        nums.sort()
        for i in range(len(nums)):
            # 如果排序后第一个数都大于0,则跳出循环,不可能有为0的三数之和
            if nums[i] > 0:
                break
            # 排序后相邻两数如果相等,则跳出当前循环继续下一次循环,相同的数只需要计算一次
            if i > 0 and nums[i] == nums[i-1]:
                continue
            # 记录i的下一个位置
            j = i + 1
            # 最后一个元素的位置
            k = len(nums) - 1
            while j < k:
                # 判断三数之和是否为0
                if nums[j] + nums[k] == -nums[i]:
                    # 把结果加入数组中
                    res_list.append([nums[i], nums[j], nums[k]])
                    # 判断j相邻元素是否相等,有的话跳过这个
                    while j < k and nums[j] == nums[j+1]: j += 1
                    # 判断后面k的相邻元素是否相等,是的话跳过
                    while j < k and nums[k] == nums[k-1]: k -= 1
                    # 没有相等则j+1,k-1,缩小范围
                    j += 1
                    k -= 1
                # 小于-nums[i]的话还能往后取
                elif nums[j] + nums[k] < -nums[i]:
                    j += 1
                else:
                    k -= 1
        return res_list


if __name__ == '__main__':
    s = Solution()
    result_list = s.threeSum([-1, 0, 1, 2, -1, -4])
    print(result_list)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值