手撕算法总结

本文探讨了多种数据结构问题的解决方案,包括LeetCode中的207题判断有环、27题下一个排列、24题两两交换链表中的节点以及1087题花括号展开。通过示例代码详细解析了如何利用链表进行操作,如检查环、排序等,并展示了二叉树的最大路径和排序链表的方法。这些算法涉及到了链表、数组、二叉树等核心数据结构的操作和优化。

【Leetcode207】判断是否有环

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        Map<Integer,List<Integer>> graph = new HashMap<>();
        int[] inDegree = new int[numCourses];
        for(int i=0;i<numCourses;i++){
            graph.put(i,new LinkedList<Integer>());
            inDegree[i]=0;
        }
        for(int []prereq:prerequisites){
            graph.get(prereq[1]).add(prereq[0]);
            inDegree[prereq[0]]++;
        }

        Queue<Integer> queue = new LinkedList<>();
        List<Integer> res = new LinkedList<>();
        for(int i=0;i<numCourses;i++){
            if(inDegree[i]==0){
                queue.offer(i);
            }
        }

        while(!queue.isEmpty()){
            int course = queue.remove();
            res.add(course);
            for(int next:graph.get(course)){
                inDegree[next]--;
                if(inDegree[next]==0){
                    queue.offer(next);
                }
            }
        }
        if(res.size()==numCourses){
            return true;
        }else{
            return false;
        }
    }
}

【leetcode27】下一个排列

class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length-2;
        while(i>=0&&nums[i]>=nums[i+1]){
            i--;
        }
        if(i>=0){
            int j=nums.length-1;
            while(j>=0&&nums[i]>=nums[j]){
                j--;
            }
            swap(nums,i,j);
        }
        reverse(nums,i+1);
    }

    public void swap(int[] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }

    public void reverse(int[] nums,int start){
        int left = start,right=nums.length-1;
        while(left<right){
            swap(nums,left,right);
            left++;
            right--;
        }
    }
}

把数组排列成最小的数

题目:
        输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个,例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

代码:

public class Main32{
    public String minNumber1(int[] nums){
        String[] res = new String[nums.length];
        int len = nums.length;
        for(int i=0;i<len;i++){
            res[i]=String.valueOf(nums[i]);
        }
        Arrays.sort(res,(x,y)->(x+y).compareTo(y+x));
        StringBuilder str=new StringBuilder();
        for(String x:res){
            str.sppend(x);
        }
        return str.toString();
    }
}

【leetcode24两两交换链表中的节点】

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode temp = dummy;
        while(temp.next!=null&&temp.next.next!=null){
            ListNode node1 = temp.next;
            ListNode node2 = temp.next.next;
            temp.next = node2;
            node1.next = node2.next;
            node2.next = node1;
            temp = node1;
        }
        return dummy.next;
    }
}

 【leetcode二叉树中最大路径】

class Solution {
    int pathSum = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        dfs(root);
        return pathSum;
    }

    public int dfs(TreeNode node){
        if(node==null) return 0;
        int left = dfs(node.left);
        int right = dfs(node.right);
        int ret = Math.max(node.val,node.val+Math.max(left,right));
        pathSum = Math.max(pathSum,Math.max(ret,node.val+left+right));
        return ret;
    }
}

/**
 * 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 sortList(ListNode head) {
        return sortList(head,null);
    }
    public ListNode sortList(ListNode head,ListNode tail){
        if(head==null){
            return head;
        }
        if(head.next == tail){
            head.next = null;
            return head;
        }
        ListNode slow = head,fast = head;
        while(fast!=tail){
            slow = slow.next;
            fast = fast.next;
            if(fast!=tail){
                fast = fast.next;
            }
        }
        ListNode mid = slow;
        ListNode list1 = sortList(head,mid);
        ListNode list2 = sortList(mid,tail);
        ListNode sorted = merge(list1,list2);
        return sorted;
    }

    public ListNode merge(ListNode head1,ListNode head2){
        ListNode dummyHead = new ListNode(0);
        ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
        while(temp1!=null&&temp2!=null){
            if(temp1.val<=temp2.val){
                temp.next = temp1;
                temp1 = temp1.next;
            }else{
                temp.next = temp2;
                temp2 = temp2.next;
            }
            temp = temp.next;
        }
        if(temp1!=null){
            temp.next=temp1;
        }else if(temp2!=null){
            temp.next = temp2;
        }
        return dummyHead.next;
    }
}

 

 

 

 

 

 

 

lc1087花括号展开

 

### 关于华为OD模式下算法面试题的解题思路 #### 题目背景与目标 华为OD(Outsourcing Dispatcher)模式下的算法面试通常涉及实际工程场景中的问题解决能力测试。这类题目不仅考察候选人的基础算法知识,还注重其对时间复杂度、空间复杂度以及代码实现效率的理解。以下是对给定内容中提到的一道典型动态规划问题的深入解析。 --- #### 动态规划问题详解 这是一道典型的 **硬币兑换问题**,属于经典的动态规划范畴。以下是具体分析: 1. **定义状态变量** 定义 `dp[j]` 表示金额为 `j` 的情况下,可以组合成该金额的不同方法数[^2]。 2. **初始化条件** 初始时设置 `dp[0] = 1`,因为当金额为零时,只有一种方式——不选任何硬币即可完成兑换。 3. **状态转移方程** 对每一种面额的硬币 `i` 进行遍历,并更新数组 `dp[]` 中的状态值。对于每一个可能的金额 `j >= i`,有如下关系: \[ dp[j] += dp[j - i] \] 其含义是:如果当前金额可以通过加入一枚价值为 `i` 的硬币来构成,则将其之前的方案数目累加到当前金额上。 4. **最终结果** 经过上述过程处理完毕之后,`dp[n]` 就代表了总金额为 `n` 时能够找到的所有不同兑换方法总数。 下面是基于此逻辑的具体代码实现: ```python def solve(n): dp = [0] * (n + 1) # 初始化DP表,默认所有情况都不可达 dp[0] = 1 # 基础情形:金额为0仅存在唯一解法 coins = [1, 2, 3] # 可供使用的硬币种类列表 for coin in coins: # 枚举每种可用硬币 for amount in range(coin, n + 1): # 更新从当前硬币面值至最大金额范围内的数据 dp[amount] += dp[amount - coin] return dp[n] # 返回所需计算的目标金额对应的结果 print(solve(3)) # 测试样例一 print(solve(2934)) # 测试更大规模输入 ``` 以上Python版本实现了完整的解决方案,其他语言如C/C++, Java, JavaScript也可以按照相同原理编写相应程序。 --- #### 时间与空间复杂度评估 - **时间复杂度**: 设共有 \( m \) 种不同的硬币类型,总额度为 \( n \),则总体运算次数大约等于两层循环乘积即 \( O(m \times n) \)[^2]。 - **空间复杂度**: 使用了一个长度为 \( n+1 \) 的辅助数组存储中间结果,因此占用额外内存大小约为 \( O(n) \)[^2]。 这种设计既满足高效求解需求又兼顾资源消耗合理性,在实际应用中有较高实用价值。 --- #### 总结 通过对上述案例的研究可以看出,针对华为OD模式下面向开发人员的技术考核环节,掌握扎实的数据结构基础知识非常重要;同时还需要具备灵活运用这些理论工具的能力以应对各种复杂的业务挑战情境。此外,熟悉常见算法模板及其变体形式也是提高答题成功率的关键所在之一。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值