2024-08-12

题目:输入两个非负 10 进制整数 A 和 B (≤230−1),输出 A+B 的 D (1<D≤10)进制数。

输入格式:

输入在一行中依次给出 3 个整数 A、B 和 D。

输出格式:

输出 A+B 的 D 进制数。

样例输入:

123 456 8

样例输出:

代码实例:




# 解法一:直接转换和计算
def convertToBaseD(number1, number2, baseD):
    return (number1 + number2) % baseD
 
# 主函数
def main():
    A, B, D = map(int, input().split())
    print(convertToBaseD(A, B, D))
 
if __name__ == "__main__":
    main()

这个代码实例中,我们定义了一个函数 convertToBaseD 来处理将两个数字转换为指定进制 D 的逻辑。然后在主函数 main 中,我们通过输入获取三个整数,并调用 convertToBaseD 函数来计算结果,最后输出结果。这个解决方案简洁明了,适合作为一种基本的解决思路。

2024-08-10

并查集是一种数据结构,用于处理一些不交集的合并及查询问题。它支持两种操作:

  1. union(a, b): 将元素a和元素b所在的集合合并,假设a和b不在同一个集合中。
  2. isConnected(a, b): 判断元素a和元素b是否属于同一个集合,即它们是否相互连通。

并查集通常使用一个数组来实现,数组中的每个元素都表示一个集合,其值可以是集合的代表元素,也可以是指向父节点的引用。

下面是Java版本的并查集实现,以及LeetCode 547. 省份数量的解决方案:




class UnionFind {
    private int[] parent;
    private int[] rank;
    private int count;
 
    public UnionFind(int n) {
        this.parent = new int[n];
        this.rank = new int[n];
        this.count = n;
        for (int i = 0; i < n; i++) {
            parent[i] = i;
            rank[i] = 0;
        }
    }
 
    public int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]); // 路径压缩
        }
        return parent[x];
    }
 
    public void union(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else {
                parent[rootY] = rootX;
                rank[rootX] += 1;
            }
            count--;
        }
    }
 
    public int getCount() {
        return count;
    }
}
 
public class Solution {
    public int findCircleNum(int[][] isConnected) {
        int n = isConnected.length;
        UnionFind uf = new UnionFind(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (isConnected[i][j] == 1) {
                    uf.union(i, j);
                }
            }
        }
        return uf.getCount();
    }
}

这段代码首先定义了一个并查集类UnionFind,包括初始化、查找、合并以及获取集合数量的方法。然后在Solution类中实现了findCircleNum方法,该方法接收一个二维数组isConnected表示省份间的直接关系,通过遍历这个数组,对需要合并的省份进行合并操作,最终返回并查集中集合的数量,即省份的数量。

2024-08-10



class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        } else {
            int leftHeight = maxDepth(root.left);
            int rightHeight = maxDepth(root.right);
            return Math.max(leftHeight, rightHeight) + 1;
        }
    }
}

这段代码是一个典型的递归解法来解决获取二叉树最大深度的问题。首先检查根节点是否为空,如果为空则返回0,表示空树的深度为0。如果不为空,则递归计算其左子树和右子树的最大深度,并返回其中较大的一个深度加1,因为加上当前节点就是整个子树的深度。

2024-08-10

题目描述:

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。

示例:

输入:nums1 = [1,3], nums2 = [2]

输出:2.00000

解释:合并数组 = [1,2,3] ,中位数 2

提示:

nums1.length == m

nums2.length == n

0 <= m <= 1000

0 <= n <= 1000

1 <= m + n <= 2000

-106 <= nums1[i], nums2[i] <= 106

进阶:

你能设计一个时间复杂度为 O(log(m + n)) 的算法解决此问题吗?

Python 解法:




class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        nums = nums1 + nums2
        nums.sort()
        n = len(nums)
        if n % 2 == 1:
            return nums[n // 2]
        else:
            return (nums[n // 2 - 1] + nums[n // 2]) / 2.0

Go 解法:




package main
 
import (
    "sort"
)
 
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
    nums := append(nums1, nums2...)
    sort.Ints(nums)
    n := len(nums)
    if n%2 == 1 {
        return float64(nums[n/2])
    } else {
        return float64(nums[n/2-1]+nums[n/2]) / 2.0
    }
}
 
func main() {
    // 测试用例
}

这两个解法都是将两个数组合并,然后排序,最后根据排序后数组的长度是奇数还是偶数来计算中位数。如果是奇数,中位数就是中间的元素;如果是偶数,中位数是中间两个元素的平均值。

2024-08-09



/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 
func rotateRight(head *ListNode, k int) *ListNode {
    if head == nil {
        return nil
    }
 
    // 计算链表长度
    length := 1
    current := head
    for current.Next != nil {
        current = current.Next
        length++
    }
 
    // 计算旋转次数
    rotateTimes := length - k%length
    if rotateTimes == length {
        return head
    }
 
    // 找到旋转起始点的前一个节点
    current.Next = head
    for i := 0; i < length - rotateTimes - 1; i++ {
        current = current.Next
    }
 
    // 新的头节点是旋转起始点的下一个节点
    newHead := current.Next
    current.Next = nil
 
    return newHead
}

这段代码首先检查了链表是否为空,并计算了链表的长度。然后根据需要旋转的次数计算出实际需要旋转的次数,以防k大于链表长度时。接着找到新的头节点,并将整个链表形成一个环,最后断开环的部分并返回新的头节点。

2024-08-08

以下是一个针对LeetCode上经典问题的Java代码解法示例,这个问题是关于删除链表中的重复节点。




// Definition for singly-linked list.
class ListNode {
    int val;
    ListNode next;
 
    ListNode(int x) {
        val = x;
        next = null;
    }
}
 
public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return head;
        }
 
        ListNode current = head;
        while (current.next != null) {
            if (current.val == current.next.val) {
                current.next = current.next.next;
            } else {
                current = current.next;
            }
        }
 
        return head;
    }
}

这段代码首先检查链表是否为空,然后遍历链表,如果发现相邻节点值相同,则删除后续重复的节点。最后返回处理后的链表头节点。这是一个典型的对链表进行节点删除操作的解法,适用于解决LeetCode上的其他相关问题。

2024-08-07

题目描述:

一只青蛙一次可以跳上台阶的一级或两级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

解法1:递归

在这个问题中,我们可以使用一种自上而下的策略,这就需要我们定义一个递归函数。这个递归函数接收一个参数n,表示台阶的数量。如果n等于0,那么就应该返回0,因为在0级台阶上不能进行任何跳法。如果n等于1,那么就只有一种跳法,返回1。如果n等于2,那么有两种跳法,返回2。否则,就有两种选择,要么跳一级,要么跳两级,所以我们的结果是跳一级的情况的结果加上跳两级的情况的结果。




func climbStairs(n int) int {
    if n <= 1 {
        return n
    }
    return climbStairs(n-1) + climbStairs(n-2)
}

解法2:动态规划

虽然递归解法很直观,但是它效率很低,因为有很多重复的计算。我们可以使用一个数组来保存中间结果,这样就可以避免重复计算。




func climbStairs(n int) int {
    if n <= 1 {
        return n
    }
    dp := make([]int, n+1)
    dp[0] = 0
    dp[1] = 1
    for i := 2; i <= n; i++ {
        dp[i] = dp[i-1] + dp[i-2]
    }
    return dp[n]
}

解法3:线性动态规划

我们还可以进一步优化空间复杂度,使用线性的动态规划。




func climbStairs(n int) int {
    if n <= 1 {
        return n
    }
    a, b := 1, 2
    for i := 2; i < n; i++ {
        a, b = b, a+b
    }
    return b
}

以上就是三种解法,分别是递归,动态规划,和线性动态规划。递归的方法效率很低,动态规划和线性动态规划的方法效率较高。

2024-08-07

题目描述:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

输入:nums = [3,2,2,3], val = 3

输出:2, nums = [2,2]

解释:函数应返回新的长度 2, 并且 nums 中的前两个元素均不是 3。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2

输出:5, nums = [0,1,4,0,3]

解释:函数应返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 4, 0, 3。

提示:

<= nums.length <= 100

<= nums[i] <= 50

<= val <= 100

Java 代码实现:




class Solution {
    public int removeElement(int[] nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
}

C 代码实现:




int removeElement(int* nums, int numsSize, int val) {
    int slowIndex = 0;
    for (int fastIndex = 0; fastIndex < numsSize; fastIndex++) {
        if (nums[fastIndex] != val) {
            nums[slowIndex] = nums[fastIndex];
            slowIndex++;
        }
    }
    return slowIndex;
}

Python3 代码实现:




class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        slowIndex = 0
        for fastIndex in range(len(nums)):
            if nums[fastIndex] != val:
                nums[slowIndex] = nums[fastIndex]
                slowIndex += 1
        return slowIndex

Go 代码实现:




func removeElement(nums []int, val int) int {
    slowIndex := 0
    for fastIndex := range nums {
        if nums[fastIndex] != val {
            nums[slowIndex] = nums[fastIndex]
            slowIndex++
        }
    }
    return slowIndex
}
2024-08-07

题目描述:

给定一个整数数组 nums,找出三个不同索引 ijk,使得 nums[i], nums[j]nums[k]乘积 最大,并返回这个最大的乘积。

示例 1:




输入: nums = [1,2,3]
输出: 6

示例 2:




输入: nums = [1,2,3,4]
输出: 24

提示:

  • 3 <= nums.length <= 104
  • -1000 <= nums[i] <= 1000

题解:




function maximumProduct(nums: number[]): number {
    nums.sort((a, b) => a - b);
    return Math.max(nums[0] * nums[1] * nums[nums.length - 1], nums[nums.length - 3] * nums[nums.length - 2] * nums[nums.length - 1]);
}

这段代码首先对数组进行排序,然后返回两种可能的最大乘积:

  1. 最大的三个数相乘
  2. 最小的两个数和第三大的数相乘

这样就可以得到数组中三个数的最大乘积。

2024-08-06

以下是针对LeetCode上第24题和第19题的Go语言解法:

第24题:两两交换链表中的节点




/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 
func swapPairs(head *ListNode) *ListNode {
    dummy := &ListNode{0, head}
    p := dummy
    for p.Next != nil && p.Next.Next != nil {
        a, b := p.Next, p.Next.Next
        p.Next = b
        a.Next = b.Next
        b.Next = a
        p = a
    }
    return dummy.Next
}

第19题:删除链表的倒数第N个节点




/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
 
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    dummy := &ListNode{0, head}
    p, q := dummy, dummy
    for i := 0; i < n+1; i++ {
        q = q.Next
    }
    for q != nil {
        p = p.Next
        q = q.Next
    }
    p.Next = p.Next.Next
    return dummy.Next
}

这两个解法都使用了快慢指针或者使用计数来找到要删除的节点的前一个节点,然后通过简单的操作删除目标节点。