精选算法入门——day2

news2024/11/27 5:31:18

精选算法入门——day2

  • 题目一
    • 题干
    • 解题思路一
    • 解题思路二
    • 解题思路三
    • 思路三代码
  • 题目二
    • 题干
    • 解题思路
    • 代码
  • 题目三
    • 题干
    • 解题思路一
    • 代码
    • 解题思路二
    • 代码
    • 解题思路三
    • 代码
  • 题目四
    • 题干
    • 解题思路
    • 代码

题目一

题干

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组
{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解题思路一

拿到这条题目自然想到统计每个数字,通过每个数字出现的次数来判断是否超过数组长度的一半,那么我们可以借用map这个数据结构,所谓的map就是键值对,键就是数组中的元素,值就是每个元素出现的次数,通过遍历整个数组将每个数组中的元素记录下来,最后比较每个元素出现的次数与数组长度一般的关系。这种方法当然可以,但是我们借用了map,不免会造成更多的空间复杂度。

解题思路二

我们可以先进行排序,那么如果真的存在超过数组长度的数,那么一定是在数组的中央,比如:
在这里插入图片描述
从图中我们可以看到,如果从最左边开始就是目标值,那么中间位置就是我们要找的数字(第一个图);如果是最右边开始就是目标值,那么中间位置也是我们要找的数字(第二个图);如果从中间某个位置开始,那么中间位置也是我们要找的数字(第三个图);但是并不是中间数就是一定满足条件的,比如,第四个图,虽然在中间位置,但是并不符合要求,所以我们找到中间位置后,通过遍历一遍数组对中间数字出现的个数进行统计,统计完在与数组长度的一半进行对比,如果大于则符合要求,如果小于则不符合要求。

解题思路三

目标条件:目标数据超过数组长度的一半。那么对数组,我们同时去掉两个不同的数字,到最后剩下的一个数就是 该数字。如果剩下两个,那么这两个也是一样的,就是结果,在其基础上把最后剩下的一个数字或者两个回到原来数组中, 将数组遍历一遍统计一下数字出现次数进行最终判断。那么具体怎么做呢?我们可以先将第一个数字记下来当作目标值(target),并把他出现的个数(times)记为1,然后向后遍历,如果出现与target相同的数字那么就将times+1,如果出现不同的数字就将times-1,当times出现为0时就将下一个数组当作target,并将times更新为1。在遍历完这个数组的时候,target就是出现次数最多的值(PS:但不一定是目标值),因此我们需要对整个数组进行遍历,对target出现次数进行统计。我们看具体的例子:
在这里插入图片描述
首先我们将1记为target,并把times记为1,向后遍历后发现2与target(1)不同,那么times-1,此时times为0,那么把后面一个数字(3)记为target,并把times记为1,再向后遍历,发现2与现在的target(3)不同,那么times-1,此时times为0,再把后面一个数字(2)记为target,并把times记为1,向后遍历,发现与target(2)相同,那么times+1,此时times为2,继续向后遍历,后面出现分别是5和4,times变为了0,此时将最后一个数字2记为target,times记为1,遍历结束,这里target就是此数组中出现次数最多的出现,这时候在进行一次遍历,将2出现的个数统计出来,并于数组长度的二分之一进行比较,得出结果,数字2就是我们要找的目标数值。

思路三代码

import java.util.*;
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型一维数组 
     * @return int整型
     */
    public int MoreThanHalfNum_Solution (int[] numbers) {
        // write code here
        if (numbers == null || numbers.length == 0){
            return 0;
        }
        int target = numbers[0];
        int times = 1;
        for(int i = 1; i < numbers.length; i++){
            if(times==0){
                target = numbers[i];
                times = 1;
            }
            if(target == numbers[i]){
                times++;
            }
            else{
                times--;
            }
        }
        times = 0;
        for(int i = 0;i<numbers.length;i++){
            if(target == numbers[i]){
                times++;
            }
        }
        return times > (numbers.length/2)? target:0;
    }
}

题目二

题干

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字
符串为We%20Are%20Happy。

解题思路

这条题目还是比较简单的,我们可以看到空格被替换成了“%20”,也就是说一个字符(空格是一个字符),被替换成了三个字符(‘%’,‘2’,‘0’),那么我们可以先统计空格的个数,通过空格的个数计算出新的字符串长度(老字符串长度+2×空格的个数),然后一个指针指向新字符串的最后一个位置,一个指针指向老字符串的最后一个位置,两个指针同时先前遍历,遍历过程中也将老字符串指针指向的字符赋值给新字符串指针,当老字符串指向空格时,把他替换成“%20”(PS:这里需要注意,因为是从后向前遍历,并且是一个一个的赋值,那么应该是先赋值“0”,然后是“2”,最后时“%”),直到两个指针完成遍历。这个题目我就不在画图了,直接上代码。

代码

public class Solution {
    public static String replaceSpace(StringBuffer str) {
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == ' ') {
                count++;
            }
        }

        int old_end = str.length() - 1;
        int new_length = str.length() + 2 * count;
        int new_end = new_length - 1;
        str.setLength(new_length);

        while (new_length >= 0 && old_end >= 0) {
            if (str.charAt(old_end) == ' ') {
                str.setCharAt(new_end, '0');
                new_end--;
                str.setCharAt(new_end, '2');
                new_end--;
                str.setCharAt(new_end, '%');
                new_end--;
                old_end--;
            } else {
                str.setCharAt(new_end,str.charAt(old_end));
                new_end--;
                old_end--;
            }
        }
        return str.toString();
    }

    public static void main(String[] args) {
        StringBuffer str = new StringBuffer("We Are Happy.");;
        System.out.println(replaceSpace(str));
    }
}

题目三

题干

输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

解题思路一

这个题目是一个非常典型的题目,有很多种方法,在这我们介绍三种,第一种,引入栈,我们知道栈是先进后出,通过将遍历的每个元素按顺序放入栈中,在把每个栈中的元素弹出来,那么就能够完成,这里也不再举具体的例子了,直接上代码。

代码

import java.util.*;
/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        if(listNode == null){
            return list;
        }
        Stack<Integer> stack = new Stack<>();

        while(listNode != null){
            stack.add(listNode.val);
            listNode = listNode.next;
        }

        while(!stack.isEmpty()){
            list.add(stack.pop());
        }
        return list;
    }
}

解题思路二

我们在原来遇到数组逆置的时候是通过双指针进行逆置,也就是说前一个指针跟后一个指针所指向的内容进行交换,前指针往后,后指针往前,直到两个指针相碰。但是单链表不行,原因就在于所谓的后指针无法往前移动,前面的节点可以往后找,但是后面的节点无法往前找。因此我们自然就想到一个思路,我们先将链表转化为数组,然后利用数组进行逆置。这个我们也不举例子了,直接上代码。

代码

import java.util.*;
/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        if(listNode == null){
            return list;
        }
        while(listNode!=null){
            list.add(listNode.val);
            listNode = listNode.next;
        }
        int i = 0;
        int j = list.size() - 1;
        while(i < j){
            int tmp = list.get(i);
            list.set(i,list.get(j));
            list.set(j,tmp);
            i++;
            j--;
        }
        return list;
    }
}

解题思路三

我们可以采用递归的方式来解决这个问题。我们假设有一个链表,我们要逆序打印每个节点,那么第一个节点是最后一个打印,也就意味着我要打印第一个,那么我要把后面所有顺序的节点都打印了,而第二个节点我要打印,也就是除了第一个节点把后面所有顺序的节点都打印了,以此类推,那么到最后一个节点,也就是最先打印节点,那么很明显这个是可以看作一个递归问题的。也就是一直往下递归,递归到最后一个节点,打印,然后出递归,打印……我们用例子理解一下。
在这里插入图片描述
比如现在我们要逆序打印:1 2 3,那么我们先进入第一层递归(1),我们发现1后面还有节点,那么进入第二层递归(2),我们发现2后面还有节点,那么进入第三层递归(3),我们发现后面没用节点了,那么就打印该节点(3),出递归,打印节点(2),出递归,打印节点(1),递归结束。如此一来打印的顺序就是3,2,1。这就是用递归解决这道问题的思路,我们上代码。

代码

import java.util.*;
/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public void function (ListNode listNode,ArrayList<Integer> list){
        if(listNode == null){
            return;
        }
        function(listNode.next,list);
        list.add(listNode.val);
    }

    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        function(listNode,list);
        return list;
    }
}

题目四

题干

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路

这条题目难度就相对于上面几道题就会难上许多,首先我们要先了解如何通过前序和后序遍历手写出二叉树。我们举个例子:
在这里插入图片描述
我们复习回顾一下二叉树的遍历方式:

前序遍历:根→左子树→右子树
中序遍历:左子树→根→右子树
后续遍历:左子树→右子树→根

由此我们可以知道前序遍历中第一个数字就是整个树中的根节点,那么在中序遍历中,就可以通过根分为左右两边,如图所示:
在这里插入图片描述
从图中我们可以看到根节点把原始的中序变为了左子树的中序和右子树的中序,而在前序当中,也有对应左子树的前序和对应右子树的前序,如图所示:
在这里插入图片描述
那么我们又可以根据左子树的前序和中序(前序:2485;中序:8425),以及右子树的前序和中序(前序:367;中序:637)进行进一步划分,以此类推,直到划分完,因此我们仍然可以用递归的方法来解决这个问题,也就是说首先利用前序的第一个节点划分中序的左右子树,根据左右子树的中序节点的个数,来确定前序遍历中对应的左右子树的前序节点的个数,那么我们就把求一整棵树的问题划分求左右子树的问题(可能有些拗口,可以对照着上面的图来理解)。我们来看代码的实现。

代码

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param preOrder int整型一维数组 
     * @param vinOrder int整型一维数组 
     * @return TreeNode类
     */
    public TreeNode function(int[] preOrder,int pre_start,int pre_end, int[] vinOrder,int vin_start, int vin_end){
        if(pre_end<pre_start||vin_end<vin_start){
            return null;
        }
        TreeNode root = new TreeNode(preOrder[pre_start]);
        for(int i = vin_start;i <= vin_end;i++){
            if(preOrder[pre_start] == vinOrder[i]){
                root.left = function(preOrder,pre_start+1,pre_start+i-vin_start,vinOrder,vin_start,i-1);
                root.right = function(preOrder,pre_start+i-vin_start+1,pre_end,vinOrder,i+1,vin_end);
                break;
            }
        }
        return root;
    }

    
    public TreeNode reConstructBinaryTree (int[] preOrder, int[] vinOrder) {
        // write code here
        if(preOrder.length==0||vinOrder.length==0||preOrder.length!=vinOrder.length){
            return null;
        }
        return function(preOrder,0,preOrder.length-1,vinOrder,0,vinOrder.length-1);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2192794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

提高顾客满意度,餐饮业如何开展客户调研?

餐饮行业需明确调研目的&#xff0c;选择合适工具&#xff0c;设计问卷&#xff0c;收集并分析数据&#xff0c;持续追踪优化。通过客户调研&#xff0c;提升服务质量、顾客满意度和竞争力&#xff0c;利用ZohoSurvey等工具实现高效调研。 一、明确调研目的 进行客户调研前&am…

ssm基于JAVA的酒店管理系统的设计与实现

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 第1章 绪论 1 1.1 选题动因 1 1.2 目的和意义 1 1.3 论文结构安排 2 第2章 开发环境与技术 3 2.1 S…

【AI知识点】置信区间(Confidence Interval)

置信区间&#xff08;Confidence Interval, CI&#xff09; 是统计学中用于估计总体参数的范围。它给出了一个区间&#xff0c;并且这个区间包含总体参数的概率等于某个指定的置信水平&#xff08;通常是 90%、95% 或 99%&#xff09;。与点估计不同&#xff0c;置信区间通过区…

i春秋云境靶场之CVE-2022-26965

1.环境搭建 提示我们后台存在rce,也就是命令执行漏洞 2.访问环境 cm - cmshttp://eci-2zeh0yf0ohu88wr26unq.cloudeci1.ichunqiu.com/ 我们可看到admin,我们点击&#xff0c;发现是一个登录页面&#xff0c;我们输入弱口令admin,登录成功 3.文件上传 我们在选项——选择主题…

C++:图的遍历

一、简介 图的遍历通常有深度优先遍历和广度优先遍历两种方式&#xff0c;这两种遍历次序对无向图和有向图都使用。 本文分别介绍基于邻接矩阵和邻接表的图的深度优先遍历和广度优先遍历&#xff0c;对于邻接矩阵和邻接表不熟悉的可翻阅&#xff1a;C&#xff1a;图的存储结构及…

dockerpull

20241006更新&#xff0c;亲测可用。 注意&#xff1a;这个方法随时可能会失效。 编辑配置文件&#xff0c;修改镜像源&#xff1a; vi /etc/docker/daemon.json {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work","…

TypeScript 第三部分 扩展

1. 声明文件 主要作用&#xff1a; 类型声明&#xff1a;为库或模块提供类型信息。全局声明&#xff1a;为全局作用域中的类型和变量提供声明。类型兼容性&#xff1a;确保第三方库或自定义代码的类型正确性。代码提示与检查&#xff1a;在开发环境中提供更好的代码提示和类型…

Sollong手机——一站式Web3生态解决方案

从定义上讲&#xff0c;Web3公司也属于互联网公司&#xff0c;不过与传统互联网公司相比&#xff0c;他们有一个很明显的特征&#xff1a;他们不断尝试做去中心化的事&#xff0c;一步步将数据和金融的控制权从美联储&#xff08;央行和金融机构&#xff09;、苹果&#xff08;…

2024/10/6周报

文章目录 摘要Abstract广西的一些污水处理厂工艺解析1. A/O工艺&#xff08;厌氧-缺氧-好氧工艺&#xff09;2. 氧化沟工艺3. MBR工艺&#xff08;膜生物反应器&#xff09;4. SBR工艺&#xff08;序批式活性污泥法&#xff09;5. 生物接触氧化法 其它补充一体化改良氧化沟工艺…

Linux的基础指令(下)

压缩包 这里不为打包和压缩做仔细的区分&#xff1b; 打包&#xff1a; 文件合并&#xff1b; 主要目的是在文件传输&#xff0c;移动时&#xff0c;能有效减少文件的缺失&#xff1b; 压缩&#xff1a;为了减小文件体积&#xff0c;内存&#xff1b; 主要目的是减小使用体…

在JS中定义和使用Vector2

概述 Vector2是GDSCript中表示二维向量的类型&#xff0c;你会发现无论在任何编程语言中&#xff0c;只要你想很好的实现2D绘图以及几何和物理相关&#xff0c;Vector2是你必须要实现的一个类。我之前学C时就写过一个C的版本。 本篇就介绍我自己在JavaScript中定义的Vector2类…

基于ssm 框架的java 开发语言的 在线教育学习平台系统设计与实现 源码 论文

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆…

AI周报(9.29-10.5)

AI应用-Elayne公司临终规划和自动化遗产结算 创业公司Elayne成立于2023年&#xff0c;由Adria Ferrier和Jake Grafenstein共同创立&#xff0c;Adria Ferrier担任CEO&#xff0c;总部位于科罗拉多州丹佛市。 Elayne公司专注于遗产规划和结算领域&#xff0c;通过人工智能技术…

实验4 循环结构

1、判断素数 【问题描述】从键盘输入一个大于1的正整数&#xff0c;判断是否为素数 【输入形式】输入一个正整数 【输出形式】输出该数是否为素数 【样例输入】10 【样例输出】10 is not a prime number 【样例说明】样例2 输入&#xff1a;-10 输出&#xff1a;error! #de…

实景三维赋能矿山安全风险监测预警

随着科技的不断进步&#xff0c;实景三维技术在矿山安全风险监测预警中的应用越来越广泛&#xff0c;它为矿山安全管理带来了革命性的变革。 一、矿山安全现状 矿山作为国家重要的能源和原材料基地&#xff0c;其安全生产直接关系到国民经济的发展和社会的稳定。然而&#xf…

【前端vue2 + element ui】Dialog 对话框:.vue组件跳转

【前端vue2 element ui】Dialog 对话框&#xff1a;.vue组件跳转 写在最前面一、父组件调用1、<template>1.1 跳转位置1.2 弹窗调用 2、<script>2.1 import2.2 export2.3 methods 二、子组件调用1、<template>2、<script>2.1 export2.2 watch和method…

不可错过!CMU最新《生成式人工智能大模型》课程:从文本、图像到多模态大模型

1. 课程简介 从生成图像和文本到生成音乐和艺术&#xff0c;生成模型一直是人工智能的关键挑战之一。本课程将探讨推动生成模型和基础模型&#xff08;Foundation Models&#xff09;最近进展的机器学习和人工智能技术。学生将学习、开发并应用最先进的算法&#xff0c;使机器…

windows下,在vscode中使用cuda进行c++编程

安装cuda CUDA Toolkit Downloads | NVIDIA Developer 这里网上教程多的是&#xff0c;在这个网址下载安装即可 我这台电脑因为重装过&#xff0c;所以省去了安装步骤&#xff0c;但是要重新配置环境变量。我重新找到了重装之前的CUDA位置(关注这个bin文件夹所在的目录) 在…

Canvas指纹:它是什么以及如何避免被Canvas指纹识别跟踪

Canvas指纹识别技术已成为追踪在线行为的一种隐蔽手段。尽管这个技术在某些方面有其正当用途&#xff0c;它也可能被用于监视我们的在线活动&#xff0c;不经我们的同意就收集个人信息。 你认为启用Canvas指纹禁用功能就能使你在网络上无迹可寻吗&#xff1f;可能需要重新考虑…

开放式耳机是什么意思?漏音吗?开放式的运动蓝牙耳机推荐

目前运动耳机市场主要分为入耳式、骨传导和开放式三类。入耳式耳机占比30%-40%&#xff0c;虽目前占比较大&#xff0c;但因在运动场景下有闷塞感、出汗不适、屏蔽外界环境音带来安全隐患等缺点&#xff0c;占比会逐渐下降。 骨传导耳机占比也为30%-40%&#xff0c;其不堵塞耳…