20190911练习题总结

本文精选力扣平台上的经典编程题目,包括判断托普利茨矩阵、生成杨辉三角、数组三等分、寻找目标和的两个数及对角线遍历矩阵等,通过详细解析算法思路与代码实现,帮助读者提升编程技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编程题

  1. (力扣766)如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。
    给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True。
    示例 1:
    输入:
    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。
    解析:要满足托普利茨矩阵则矩阵每一方向由左上到右下的对角线上具有相同元素,所有右上角和左下角只有一个元素,因此这两个角可以忽略,然后就是给矩阵标注上角标,也就是说只有遍历完以(0,0)所在的哪一行和(1,0)所在的那一列,只有全部都满足每一个方向上的对角线上具有连续相等的元素,这个矩阵就属于托普利茨矩阵,由此也就是说只要有一个不满足每一个方向上的对角线具有相等元素这个条件就不是托普利茨矩阵。
public boolean isToeplitzMatrix(int[][] matrix) {
		int row = matrix.length;
		int col = matrix[0].length;
		// 列方向
		for (int i = 0; i < col - 1; i++) {
			int x = 1;
			int y = i + 1;
			while (x >= 0 && x < row && y >= 0 && y < col) {
				if (matrix[x][y] != matrix[0][i]) {
					return false;
				}
				x++;
				y++;
			}
		}
		// 行方向
		for (int i = 1; i < row - 1; i++) {
			int x = i + 1;
			int y = 1;
			while (x >= 0 && x < row && y >= 0 && y < col) {
				if (matrix[x][y] != matrix[i][0]) {
					return false;
				}
				x++;
				y++;
			}
		}
		return true;
	}
  1. (力扣118杨辉三角)给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
    在杨辉三角中,每个数是它左上方和右上方的数的和。
    示例:
    输入: 5
    输出:
    [1],
    [1,1],
    [1,2,1],
    [1,3,3,1],
    [1,4,6,4,1]
 public List<List<Integer>>generate(int numRows){
    	List<List<Integer>> lists=new ArrayList<List<Integer>>();
    	for(int i=1;i<=numRows;i++) {
    		ArrayList<Integer> list=new ArrayList<Integer>();
    		for(int j=0;j<i;j++) {
    			if(j==0||j==i-1) {
    				list.add(1);
    			}else {
    				list.add(lists.get(i-2).get(j)+lists.get(i-2).get(j-1));
    			}
    		}
    		lists.add(list);
    	}
    	return lists;
    }
  1. (力扣1013)给定一个整数数组 A,只有我们可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。
    形式上,如果我们可以找出索引 i+1 < j 且满足 (A[0] + A[1] + … + A[i] == A[i+1] + A[i+2] + … + A[j-1] == A[j] + A[j-1] + … + A[A.length - 1]) 就可以将数组三等分。
    示例 1:
    输出:[0,2,1,-6,6,-7,9,1,2,0,1]
    输出:true
    解释:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1
    示例 2:
    输入:[0,2,1,-6,6,7,9,-1,2,0,1]
    输出:false
    示例 3:
    输入:[3,3,6,5,-2,2,5,1,-9,4]
    输出:true
    解释:3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4
    提示:
    3 <= A.length <= 50000
    -10000 <= A[i] <= 10000

解析:先遍历整个数组,求出数组元素的和,然后将和除3得到三个相等部分的各个和。然后依次遍历数组,将每次遍历的数进行累积,只要和等于求出来的每部分的和,就进行下一组的累计计算,一次循环。

 public boolean canThreePartsEqualSum(int [] A) {
     //先算和再除3
		int sum=0;
		for(int num:A){
			sum+=num;
		}
		int key=sum/3;
		int temp=0;
		for(int i=0;i<A.length;i++){
			key-=A[i];
			if(key==0){
				temp++;
				key=sum/3;
			}
		}
		return temp==3;
		}
  1. (力扣167)给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
    函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
    说明:
    返回的下标值(index1 和 index2)不是从零开始的。
    你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
    示例:
    输入: numbers = [2, 7, 11, 15], target = 9
    输出: [1,2]
    解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
    解析:已知给的是升序排列的有序数组,要找到两个数相加之和等于目标数,那么从头开始遍历,找到第一个数,需要找另一个数(目标数-第一个数),那么因为是有序数组,所以折半查找(二分查找)比较合适,如果没找到继续循环,所以需要一个指针来指向元素所对应的角标,如果没找到,角标+1继续循环查找
public int[] twoSum(int[] numbers, int target) {
		for (int i = 0; i < numbers.length; i++) {
			int index = binarySearch(numbers, i + 1, numbers.length - 1, target - numbers[i]);
			if (index != -1) {
				return new int[] { i + 1, index + 1 };
			}
		}
		return null;
	}

	public int binarySearch(int[] arr, int begin, int end, int key) {
		// TODO Auto-generated method stub
		int min = begin;
		int max = end;
		int mid = (min + max) / 2;
		while (arr[mid] != key) {
			if (arr[mid] > key) {
				max = mid - 1;
			} else if (arr[mid] < key) {
				min = mid + 1;
			}
			if (min > max) {
				return -1;
			}
			mid = (min + max) / 2;
		}
		return mid;
	}
  1. (力扣498)给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
    示例:
    输入:
    [
    [ 1, 2, 3 ],
    [ 4, 5, 6 ],
    [ 7, 8, 9 ]
    ]
    输出: [1,2,4,7,5,3,6,8,9]
    解析:二维数组找规律看角标
    [0 0, 0 1, 0 2 ],
    [1 0, 1 1, 1 2 ],
    [ 2 0 , 2 1, 2 2 ]
    可见同一个对角线的元素角标值相等,并且合围偶数往右上方向,和为奇数往左下方向,往右上循环的条件有如果行遍历到了最后但是列没有走到末尾,则行不变,列+1;列如果到了末尾,行+1;其他情况行-1和列+1。往左下的循环条件如果列遍历到了最后但是行没有走到末尾,则列不变,行+1;行如果到了末尾,列+1;其他情况行+1和列-1
	public int[] findDiagonalOrder(int[][] matrix) {
		/*
		 * matrix==null 什么都没有
		 *  matrix.length 有数组但一个元素都没有 
		 * col==0 有行 但是每行没元素 
		 * row==1 只有一行(不管没有元素
		 * ) col==1 只有一列(多个行 每行只有一个元素)
		 */
		if (matrix == null || matrix.length == 0) {
			return new int[] {};
		}
		int row = matrix.length;
		int col = matrix[0].length;
		if (col == 0) {
			return new int[] {};
		}
		// 二维数组只有一行
		if (row == 1) {
			return matrix[0];
		}
		// 二维数组只有一列
		int[] nums = new int[row * col];
		if (col == 1) {
			for (int i = 0; i < row; i++) {
				nums[i] = matrix[i][0];
			}
			return nums;
		}

		int i = 0;
		int j = 0;
		int index = 0;
		while (i < row && j < col) {
			// 读取(i,j)元素
			nums[index++] = matrix[i][j];
			if ((i + j) % 2 == 0) {// 右上
				if (i == 0 && j != col - 1) {
					j++;
				} else if (j == col - 1) {
					i++;
				} else {
					i--;
					j++;
				}
			} else {// 左下
				if (j == 0 && i != row - 1) {
					i++;
				} else if (i == row - 1) {
					j++;
				} else {
					i++;
					j--;
				}
			}
		}
		return nums;

	}

}

  1. (力扣724)给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
    我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
    如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
    示例 1:
    输入:
    nums = [1, 7, 3, 6, 5, 6]
    输出: 3
    解释:
    索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
    同时, 3 也是第一个符合要求的中心索引。
    示例 2:
    输入:
    nums = [1, 2, 3]
    输出: -1
    解释:
    数组中不存在满足此条件的中心索引。
    说明:
    nums 的长度范围为 [0, 10000]。
    任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。
    解析:先遍历数组,对数组元素求和,然后定义一个指针i指向元素的值,再定义两个变量(左边的和、右边的和),其中右边的和=总和-左边的和-i所对应的元素值,从左往右第一个元素开始遍历然后计算左边、有的分别的和,只要左边和等于右边和,则i所指向的元素就是索要求解的中心索引,则返回其所指向的元素值
public int pivotIndex(int[] nums) {
		if (nums == null) {
			return -1;
		}
		int sum = 0;
		int leftSum = 0;
		int rightSum = 0;
		for (int num : nums) {
			sum += num;
		}
		for (int i = 0; i < nums.length; i++) {
			if (i == 0) {
				leftSum = 0;
			} else {
				leftSum += nums[i - 1];
			}
			rightSum = sum - leftSum - nums[i];
			if (leftSum == rightSum) {
				return i;
			}
		}
		return -1;
	}

选择题

  1. 现有初始状态均为空的栈X和队列Y,元素a,b,c,d,e,f,g依次进入栈X,每个元素出栈后即入队列Y,如果出队的顺序为b,c,f,e,g,d,a,则要求栈X最小容量
    6
    5
    4
    3
    答案:4
    解析:栈—先进后出,队列—先进先出,所以出队顺序b,c,f,e,g,d,a即入队顺序,同样也是出栈顺序,b先出a b 都入栈,容量为2,b出栈,容量为1,c进然后出,容量为1,f要出则d e f要进栈,容量为4,f出容量为3,e出容量为2

  2. 设有一个数组Q[1…m]表示的环形队列,约定f为当前对头元素在数组中的位置,r为队尾元素的后一位置(按顺时针方向)若队列非空,则计算队列中元素的个数的勇士应为
    (m+r-f)mod m
    r-f
    (m-r-f) mod m
    (m-r+f) mod m
    答案: (m+r-f)mod m

  3. 若用一个大小为6的数组来实现循环队列,队尾指针是rear、对头是front。当前rear和front的值分别为0和3,定从队列中删除一个元素,再加入两个元素后,rear和front的值分别为
    1和5
    2和4
    4和2
    5和1
    答案:2和4

  4. 以下操作中,数组比链表速度更快的是
    原地逆序
    头部插入
    返回中间节点
    返回头部节点
    选择随机节点
    答案:原地逆序 选择随机节点

  5. 两个栈共享一片来内需内存空间时,为提高内存利用率,减少溢出机会,应把两个栈的栈底分别设在这片内存空间的两端


    答案:对

  6. 若有一个栈的输入序列是1,2,3,…,n,输出序列的第一个元素是n,则第i个输出的元素是
    n-i
    n-i+1
    n-i-1
    不确定
    答案: n-i+1

  7. 设有一个长度为n的顺序表,要在第i(从1开始)个元素之前(也就是插入元素作为新表的第i个元素),则移动元素的个数为
    n-i+1
    n-i
    n-i+1
    i
    答案: n-i+1

  8. 对线性表采用折半查找,该线性表必须
    元素按值有序排列
    采用顺序结构
    元素按值有序排列,并采用顺序存储结构
    元素按值有序排列,并采用链式存储结构
    答案: 元素按值有序排列

  9. 下面描述正确的为
    线性表的逻辑顺序与物理顺序总是一致的
    线性表的顺序存储表示优于链式存储表示
    新型表若采用链式存储表示所有结点直接的存储单元地址可连续可不连续
    二维数组是其数组元素为线性表的线性表
    答案: 新型表若采用链式存储表示所有结点直接的存储单元地址可连续可不连续
    二维数组是其数组元素为线性表的线性表

  10. 设栈的顺序存储空间为S(1:m),初始状态为top=m+1。现经过一系列正常的入栈和退栈操作后,top=0,则栈中的元素个数为
    不可能
    m+1
    1
    m
    答案:m
    解析:top=m+1说明栈顶在表尾,top=0表示栈顶到了表头

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值