LeetCode第一天
只记录中高等难度的题(高等怕的很,暂时中等)
一、1254. 统计封闭岛屿的数目
二维矩阵 grid 由 0 (土地)和 1 (水)组成。岛是由最大的4个方向连通的 0 组成的群,封闭岛是一个 完全 由1包围(左、上、右、下)的岛。
请返回 封闭岛屿 的数目。
示例 1
输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2
解释:
灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。
class Solution {
public int closedIsland(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int rel = 0;
for(int i = 0;i<m;i++){
dfs(grid,i,0);
dfs(grid,i,n-1);
}
for(int i = 0;i<n;i++){
dfs(grid,0,i);
dfs(grid,m-1,i);
}
for(int i = 0;i<m;i++){
for(int j = 0;j<n;j++){
if(grid[i][j] == 0){
dfs(grid,i,j);
rel++;
}
}
}
return rel;
}
public void dfs(int[][] grid,int m,int n){
if(m < 0||n < 0||m >= grid.length||n >= grid[0].length||grid[m][n] == 1){
return;
}
grid[m][n] = 1;
dfs(grid,m+1,n);
dfs(grid,m-1,n);
dfs(grid,m,n+1);
dfs(grid,m,n-1);
}
}
个人题解:
动态规划(DFS)。把边缘的陆地通过动态规划找寻相邻的陆地一起排除变成海,这个时候如果还有陆地那一定就是孤岛,每找到一个陆地就动态规划的把与之相邻的所有陆地都变成海同时算作一块陆地。
二、684. 冗余连接
树可以看成是一个连通且 无环 的 无向 图。
给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。
示例 1:
输入: edges = [[1,2], [1,3], [2,3]]
输出: [2,3]
class Solution {
public int[] findRedundantConnection(int[][] edges) {
int m = edges.length;
int[] a = new int[m+1];
for(int i = 1;i <= m;i++){
a[i] = i;
}
for(int i = 0;i < m;i++){
int[] b = edges[i];
int node1 = b[0],node2 = b[1];
if(find(a,node1) != find(a,node2)){
union(a,node1,node2);
}
else{
return b;
}
}
return new int[0];
}
public void union(int[] a,int node1,int node2){
a[find(a,node1)] = find(a,node2);
}
public int find(int[] a,int node){
if(a[node] != node){
a[node] = a[find(a,a[node])];
}
return a[node];
}
}
个人题解:
并查集。n个节点n条边,多了一条边,假设每个点都不是连通的,所以用一个数字把所有点归属到不同的集合里,对应下标的值相同就说明两个点连通,遍历所有边,把点跟点连起来,如果发现一条边的两个点已经是连通的就说明这条边是多余的,返回这条边就行了。
三、2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null,tail = null;
int carry = 0;
while(l1 != null||l2 != null){
int n1 = l1 != null ? l1.val:0;
int n2 = l2 != null ? l2.val:0;
int sum = n1 + n2 +carry;
if(head == null){
head = tail = new ListNode(sum%10);
}
else{
tail.next = new ListNode(sum%10);
tail = tail.next;
}
carry = sum / 10;
if(l1 != null){
l1 = l1.next;
}
if(l2 != null){
l2 = l2.next;
}
}
if(carry != 0){
tail.next = new ListNode(carry);
}
return head;
}
}
个人题解:
链表结构体。要返回的是头节点,所以要用一个链表保存头节点。把两个链表通过补0扩成一样的长度,然后从头往后一位一位计算,再计算进位carry,最后如果进位还大于1,就需要再把链表扩大一位。