现在前面:本文大概有1w字左右,阅读时间大概为10分钟左右,由于本人刚开始写文章,文章总体质量不高,都是以文字描述,没有结合图片详细讲解,后期会补上,还望各位多多包涵。
题目一:给一个数组,按照每个数字的个位数进行排序,如果个位数相同,则保持其相对位置保持不变,如果为负数,取其个位数的绝对值然后在根据个位数进行排序 例一:[34,10,12,11,-1,29,8] 结果:[10,11,-1,12 ,34,8,29] 例二: [2,45,21,22,71,9] 结果为:[21,71,2,22,45,9],请编写代码实现该功能。
题目分析以及实现思路:
题目分析:题目要求按照以每个数字的个位数进行排序,并且个位数相同的保持相对位置保持不变,如果出现负数的话,应该首先取绝对值然后再求个位数。
实现思路:①首先应该知道每个数字的个位数都应该包含在0-9当中。 ②然后给定一个临时数组分别求出每个数字的个位数(都取绝对值,然后%10可以解决这个问题), ③此时我们应该清楚:临时数组里面每个数存的是给定数组对应下标数字的个位数,之后进行排序。 ④对于数组进行排序并且保持相对位置保持不变,有人可能会觉得不知所措。这就需要我们仔细分析题目,我们知道临时数组存的是每个数字对应的个位数,那我们可以从0-9循环10次(记为循环变量),每次对临时数组进行遍历,找出临时数组所对应的值是否等于当前循环变量的值,如果循环临时数组的值等于该循环变量的值,此时,根据临时数组所对应的下标,得到给定数组此下标的值,加入结果集中,当10次循环完成也就是排序完成并且也保持数组中个位数相同的数字相对应的位置也保持不变。
实现代码如下:
public class Main {
public static void main(String[] args) {
int arr[]={34,10,12,11,-1,29,8};
new Main().sortOfLastNumber(arr);
}
//按照个位数进行排序
public int[] sortOfLastNumber(int arr[]){
//存放每一位数字的个位数的临时数组
int[]temp=new int[arr.length];
//对临时数组进行初始化操作
for(int i=0;i<arr.length;i++){
temp[i]=Math.abs(arr[i])%10;
}
int result[]=new int[arr.length];
int k=0;
//因为每个数的的个位数都在0-9之间
for(int i=0;i<=9;i++){
//保持相对位置不变的情况下,按照个位数进行排序
for(int j=0;j<temp.length;j++)
//看个位数是否等于当前循环的数,即就是按照各位排序
if(temp[j]==i){
result[k]=arr[j];
System.out.print(result[k]+" ");
k++;
}
}
return result;
}
}
题目二:给你一个单词,并且给你一个字符数组,你可以从某一点开始进行查找,返回该数组是否包含该单词, 如果包含该单词就返回该单词第一个字母在该数组的位置(即第几行,第几列)(说明不能跳跃查找,必须是连续的,并且已经走过的路径不能再走,即就是不能回头,区分大小写)例如:给一个单词:hellword 给一个字符数组:
['a', 'c', 'b', 'f', 'h']
['d', 'r', 'o' ,'l', 'e']
['v', 'h', 'w', 'l', 'p']
['b', 'c', 'x', 't', 'q']
['p', 'q', 'h', 'g', 'q']
结果为:结果为:1,5
例二: ['H','a','v','b','g'] ['y','Q','G','c','e'] ['f','D','H','e','Q'] ['v','q','d','l','l'] ['j','p','r','o','w']
结果为:NO(如果不区分大小写,返回:3,3,但是题目要求区分大小写)
题目分析以及实现思路:
实现代码如下:
import java.util.*;
public class Main_1 {
//定义一个方向数组,即就是某一个坐标,可以在前后左右进行移动
public static int[][]direction={{-1,0},{0,1},{0,-1},{1,0}};
//定义一个boolean数组,存放已经走过的位置,防止其往回走
public static boolean used[][];
//判断数组下标是否越界
public static boolean isValid(int x,int y,char[][]chars){
if(x<0 || y<0 || x>=chars.length || y>=chars[0].length)return false;
return true;
}
//深度搜索算法
public static boolean dfs(char[][]arr,int x,int y,String target,String temp,boolean[][]used){
//如果给定的目标字符串可以在该字符数组中找到,返回true;
if(target.equals(temp)){
return true;
}
//如果临时的结果字符串长度大于给定的字符串长度,则肯定两个字符串不相等,即返回false
if(temp.length()>target.length()){
return false;
}
//如果以上条件都不满足,说明临时结果字符串长度小于给定的字符串长度,
// 即进行深度操作:临时字符串加上当前字符,该坐标位置已经别访问
temp+=arr[x][y];
used[x][y]=true;
//然后从该坐标向其前后左右进行再次深度查询
for(int i=0;i<direction.length;i++){
//判断下个查询坐标位置是否合法
if(isValid(x+direction[i][0],y+direction[i][1],arr)){
//下个坐标位置已经合法,判断下个位置是否已近访问过
if(used[x+direction[i][0]][y+direction[i][1]]==false){
//下个位置坐标合法且没有访问过,就深度查询下个位置的坐标情况
if( dfs(arr,x+direction[i][0],y+direction[i][1],target,temp,used)){
//如果满足给定的条件即返回true;
return true;
}
}
}
}
//回溯操作:
//该位置深度查找不满足,则该临时变量不加该位置的字符
temp=temp.substring(0,temp.length()-1);
//那么该位置也就不访问,即回退
used[x][y]=false;
//该位置前后左右都查不到,说明从该位置出发,查不到给定的目标字符串
return false;
}
public static void main(String[] args){
//测试前的数据初始化操作
Scanner scanner=new Scanner(System.in);
String str_Mn=scanner.nextLine();
String[]s1=str_Mn.split(" ");
int n=Integer.parseInt(s1[0]);
int m=Integer.parseInt(s1[1]);
//数组的长度与宽度
String target=scanner.nextLine();
if( target.length()<=0){
System.out.println("NO");
return;
}
char[][]arr_c=new char[n][m];
used=new boolean[n][m];
//字符数组的初始化操作
for(int i=0;i<n;i++){
String temp=scanner.nextLine();
arr_c[i]=temp.toCharArray();
}
for (int h = 0; h <n ; h++) {
for (int k = 0; k <m ; k++) {
used[h][k]=false;
}
}
//对数组每个位置进行深度搜索
for (int i = 0; i <n ; i++) {
for (int j = 0; j <m ; j++) {
//如果一开始的字符与给定字符串的头个字符不相等,进行下一个位置的深度搜索
if(arr_c[i][j]!=target.charAt(0))continue;
String string="";
//如果深度搜索结果为true,说明找到
boolean result= dfs(arr_c,i,j,target,string,used);
if(result==true){
//输出从那个位置找到该字符串的(输出找到的位置)
System.out.print((i+1)+" "+(j+1));
return;
}
}
}
//整个数组搜索完了,没找到目标字符串,则返回false;
System.out.print("NO");
}
}
代码实现如下:
public class sort {
static LinkedList<Integer> a = new LinkedList<>();
public static void main(String[] args) {
sort b = new sort();
//初始化测试用例
for (int i = 0; i < 10; i++) {
int temp = (int) (Math.random() * 10);
b.addNumber(temp);
}
int[] arr = new int[10];
//查看添加的数字是否有序
for (int i = 0; i < a.size(); i++) {
System.out.print(a.get(i) + " ");
arr[i] = a.get(i);
}
System.out.println();
//二分查找法是否正确
for (int i = -1; i <= 11; i++) {
boolean result = b.searchNumber(arr, i);
System.out.println(i + ":" + result);
}
}
//添加一个数字,使其添加后的数组也是有序的
// (使用Java提供的linkedlist集合即为双向链表,增加数字的效率高)
public void addNumber(int value) {
//如果链表的长度为0直接添加
if (a.size() == 0) {
a.add(value);
return;
}
//查找该插入的位置
for (int i = 0; i < a.size(); i++) {
if (a.get(i) <= value) continue;
else {
//把该数字插入相应的位置
a.add(i, value);
break;
}
}
}
//二分查找法
public boolean searchNumber(int a[], int value) {
//边界情况进行查询
if (a.length <= 0) {
return false;
}
if(value>a[a.length-1] || value< a[0] )return false;
int i = 0, j = a.length, mid = (i + j) / 2;
//二分查找发的精髓
while (i <=j) {
if (a[mid] == value) {
return true;
}
if (a[mid] > value) {
j = mid - 1;
} else {
i = mid + 1;
}
mid = (i + j) / 2;
}
return false;
}
}
题目一:有一组订单列表orderList,每个订单有x个货物其中货物编号是连续的. 例如第一号订单:[1,5,20] 解释:一号订单要定编号为1到5的商品,其中每个商品定20件。 那么给你一组订单列表,分别求出每个编号商品需要的数量。 举例:订单列表:[0,3,20],[3,5,15],[4,6,12]; 结果为:[20,20,20,35,27,27,12];请实现该算法。
题目分析以及实现思路:
代码实现如下:
public class Solution_1 {
//这是我回来测试我当时写的
public static void main(String[] args) {
int[][]orderList={{0,3,20},{3,5,15},{4,6,12}};
new Solution_1().computeProductNumber(orderList);
}
//以下代码是我当时笔试时候写的
public int[] computeProductNumber(int[][]orderList){
Map<Integer,Integer> result=new HashMap<>();
for(int i=0;i<orderList.length;i++){
//对数组每一个行进行操作(即对每一种类型商品所需要的数量进行操作)
for(int j=orderList[i][0];j<=orderList[i][1];j++){
//当前map中是否包含该商品
if (!result.containsKey(j)){
//如果不包含,就添加该商品的编号和需要的数量
result.put(j,orderList[i][2]);
}
else{
//当前map中包含该商品,则要继续增加该商品的数量
int temp=result.get(j);
result.put(j,orderList[i][2]+temp);
}
}
}
int []re=new int[result.size()];
int k=0;
//最后把map转化为数组
for(int i=0;i<result.size();i++){
re[k]=result.get(i);
System.out.print(re[k]+" ");
k++;
}
//返回结果
return re;
}
}
题目二:给定一个数字字符串,任意交换其中两个数字,是否能把原数字变成最小的数字。 例如: "421" 交换4与1 可以变成124即为最小的,则返回true "3241" 返回false, 因为交换1与3,变成1243而最小的数字为:1234,所以返回false 请实现该算法(所给的数字,不包含0)
题目分析以及实现思路:
代码实现如下:
public class Solution_2 {
public static void main(String[] args) {
String number="3241";//"421"
System.out.print(new Solution_2().isConstructMinNumber(number));
}
public static String swapAndResult(int[]arr,int i,int j){
//交换数组下标的(i,j)两个位置的数字
String result="";
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
//得到交换后的字符串
for(int k=0;k< arr.length;k++){
result+=arr[k];
}
//还原该数组
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
return result;
}
public boolean isConstructMinNumber(String number){
boolean result=false;
int[] arr=new int[number.length()];
int temp[]=new int[number.length()];
//初始化该数组
for (int i = 0; i < number.length(); i++) {
arr[i]=number.charAt(i)-'0';
temp[i]=arr[i];
}
//对临时数组进行排序
Arrays.sort(temp);
String re="";
//得到临时数组排序后的字符串
for (int i = 0; i < temp.length; i++) {
re+=temp[i];
}
for(int i=0;i<arr.length;i++){
String re1="";
for(int j=i+1;j<arr.length;j++){
//交换i,j俩个位置
re1=swapAndResult(arr,i,j);
//看结果是否等于临时数组排序后字符串
if(re.equals(re1)){
//如果等于说明交换i,j两位可以把该字符串转化为最小的字符串
result=true;
return result;
}
}
}
//交换所有的(i,j)位置都不能转化,返回false
return result;
}
}
题目三:一台电脑有双核cpu,每个时刻两个cpu同时运行,现给你一个数组,其中分别对应每个应用的运行时间,求出运行完该组应用的最短时间例如: 例一:[12,20,30] 结果为:32 例二:[4,7,15] 结果为:15 例三:[100,45,55] 结果为:100。请编码实现该代码。
题目分析以及实现思路:
题目分析: 本题需要使用贪心算法(对于贪心算法,这个没有固定的模板,需要自己在撸代码的时候加以体会。),找出最短运行时间,我们可以这样想:先找出数组中最大的运行时间的程序,把这个程序给一个cpu进行处理,然后在该时间段内,另一个CPU可以处理其他运行时间比他小的应用程序,这样当最大运行时间结束之后,另一个cpu有可能处理了其他多个应用程序,但是这些应用程序的总运行时间小于或者等于该最大运行时间,(运行结果集加上该运行时间。),然后循环进行以上步骤,直到所有运行程序都执行完成,最小运行时间也就可以计算出来了。(可能说的比较笼统,可以参照代码具体理解。)
实现思路:这个题目实现思路,本人讲的比较模糊,感觉自己知道怎么实现,但是表达有点问题。可能有点模糊不清,直接上代码,后续整理好思路再补上这个题目的实现思路。
实现代码如下:
public class Solution_3 {
int appNumber;
//查找该数应用中最大运行时间的下标方法
int searchMaxIndex(int arr[]){
int index=-1;
int max=0;
//查找最大的运行时间,记录其下标
for(int i=0;i<arr.length;i++){
if(arr[i]==0)continue;
else{
if(arr[i]>=max){
max=arr[i];
index=i;
}
}
}
return index;
}
public static void main(String[] args) {
int arr[]={4,7,15};//{1,1,1,1,1,2};
new Solution_3().computeMinMintue(arr);
}
public void combineArrs(int arr[],int max){
//找打最大运行时间,在判断其余的应用在该时间内是否看可以完整运行
for(int i=0;i<arr.length;i++){
//如果当前应用已近运行完成,继续看下一个应用
if(arr[i]==0) continue;
//如果当前程序的运行时间小于最大运行时间,
// 即该程序运行完成以后,还有其余的时间给其他的程序运行
if(arr[i]<=max){
max=max-arr[i];
appNumber--;
arr[i]=0;
if(max==0)return;
else continue;
}
//如果当前应用运行时间大于当前还剩的时间,则当前还剩的时间置为0
//并且当前应用运行时间减去还剩的时间,即为当前应用还需要的时间
if(arr[i]>max){
arr[i]=arr[i]-max;
return;
}
}
}
public int computeMinMintue(int[]arr){
int result=0;
//对应用程序运行时间进行分类
Arrays.sort(arr);
int n=arr.length;
appNumber=n;
//所有程序都运行完成,结束任务
while (appNumber!=0){
//查找剩余程序运行最大时间
int index=searchMaxIndex(arr);
//如果所有的程序都运行完成,结束循环
if(index==-1) break;
int temp=arr[index];
//需要最短的时间结果
result+=arr[index];
//该最大程序运行结束,则其个数减一
appNumber--;
//并且该程序运行时间为0
arr[index]=0;
//另一个cpu在该段时间内进行其他应用程序的操作
combineArrs(arr,temp);
}
System.out.print(result);
//最后返回最少的运行时间
return result;
}
}
题目一:写一个堆排序(和面试官在线撸代码)。
题目分析以及实现思路:
题目分析:首先堆排序是排序算法中比较重要的一个排序算法,其时间复杂度为:nlog₂(n)。堆排序的难点在于:剪枝与构建堆。其中构建堆有大堆与小堆。在构建大小堆的时候,注意数组下标(一般是从数组下标1的位置开始,这样的好处就是:很容易确定该节点的左右孩子节点与该节点的父节点,便于构建堆,坏处就是:浪费一个存储空间。)
实现思路:对于堆排序算法,网上有许多非常优秀的讲解,这里我只是简单讲一下我给个人对堆排序算法理解:1.首先初始化堆(即构建大堆或者小堆,这里我是构建大堆。这里说明一下大堆即为:该节点比子节点的值大,比父节点的值小,小堆与大堆相反)。初始化堆栈的时候从最后一个有子节点的节点开始,也就是从n/2下标的位置开始(n代表锁给数组的长度,忽略下标为0的值),然后找到该节点下的最大的节点,交换该节点与子节点最大值得节点。该节点构建堆完成,然后继续进行上一个节点,重复以上步骤,直到节点下标小于1为止,这样下标为1的节点为该堆中值为最大的节点。2.接下来就是剪枝操作:因为初始化之后,第一个节点为最大的值,可以把第一个节点的值与最后一个节点的值交换,这样最大一个值已经排序完成,数组长度减一(这里并不是数组长度变为n-1,而是以后构建堆的时候该节点不参与排序),这就是剪枝操作。这一步操作完成以后还需要再次进行构建堆,因为交换了两个节点的元素就破坏了原有堆的性质。所以就需要重新构建堆,这里需要注意构建堆的时候数组长度减一,因为最后一个不需要参与此次堆构建的过程中。3.重复以上步骤n-1次就能完成排序。
实现代码如下:
public class Solution1 {
//构建大堆栈
void sift(int arr[],int low,int high){
//从数组下标1开始的
int i= low,j=i*2;
int temp=arr[i];
//构建大堆的关键
while(j<=high){
//找到i节点的子节点最大值
if(j<high && arr[j]<arr[j+1]){
j++;
}
//如果当前low节点的值小于子节点的最大值,则交换父子节点的值
if(temp<arr[j]){
arr[i]=arr[j];
//继续往下找
i=j;
j=i*2;
}
//否则就退出循环
else{
break;
}
}
//把low节点的值放到该放的位置上
arr[i]=temp;
}
void heapSort(int arr[],int n){
int i,temp;
//初始化大队栈
for( i=n/2;i>=1;i--){
sift(arr,i,n);
}
//剪枝操作
//已经构建好了大堆栈,即第一数组为该数组的最大值,
// 与还没有排序好的数组的最后一个位置进行交换,之后在对其余还没排序的数组进行构建大堆栈
for(i=n;i>=1;i--){
//剪枝操作
temp=arr[1];
arr[1]=arr[i];
arr[i]=temp;
//对其余没有排序好的数组进行构建大堆栈,再次执行之前的操作
sift(arr,1,i-1);
}
for(int h=1;h<arr.length;h++){
System.out.print(arr[h]+" ");
}
}
}
题目二:给定一个字符串,然后把该字符串转化为阿拉伯数字, 其中转化流程为:给定一个字符串:例1."TwoSixDoubleFour" 结果为:2644例2."EightFourDoubleZero" 结果为:8400 例3. "DoubleZeroDouble" 结果为:-1 (解释,最后一个Double后面没有数字) 请编码实现该功能。(和面试官在线撸代码)
题目分析以及实现思路:
题目分析:对于该题目的难点就是怎么分割字符串并且按照单词分割,还有一个就是对于Double这个单词怎么实现重复出现该单词后面一个单词的阿拉伯数字。
实现思路:首先可以分析,字符串只出现10个单词和一个DOuble单词,这样就可以使用键值对的HashMap形式的数据结构,对于key是String类型的,value是Integer形式的。进行初始化该HashMap对象,然后定义一个变量,遍历所给的字符串,当遇到一个字符串包含在hashMap对象中这样可以根据当前的字符串(key)找到该字符串所对应的值(value),把改值加入到结果集中,当遇到Double这个单词,对于其后面的单词,加入两次到结果集中,然后重复以上步骤直到结束循环。
实现代码如下:
public class Solution {
//构建一个key-value键值对,存放英文字母相对应的数字HashMap集合
static HashMap<String, Integer> temp = new HashMap<>();
public static void main(String[] args) {
String[] str = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
//对Map集合进行初始化操作
for (int i = 0; i <= 9; i++) {
temp.put(str[i], i);
}
//测试代码
String str1="DoubleZeroDouble";//DoubleZeroDouble
String result= new intervier1.Solution().computeResult(str1);
System.out.print(result);
}
//具体功能实现的方法
public String computeResult(String str) {
//临时结果变量
String result = "";
//最终结果
String finalResult = "";
//标志位:(作用:看某个英文单词前面是否有Double)
boolean flag=false;
//给定字符串的每个字母进行操作
for (int i = 0; i < str.length(); i++) {
result += str.charAt(i);
//如果当前Map集合中存在某个字符串与当前临时变量的结果相等
if (temp.containsKey(result)) {
//判断前面单词是否是Double
if(flag==true) {
//如果是Double则最终结果加两次
finalResult += temp.get(result);
finalResult+=temp.get(result);
//该字母已经使用,使临时结果为空
result = "";
//Double已经使用,则把标志位改成false
flag=false;
}else{
//如果前面没有Double,最终结果只用加一次该数字
finalResult+=temp.get(result);
result = "";
}
}
//如果Map集合中不存在当前临时结果,则看该临时结果是否等于Double
if (result.equals("Double")) {
//如果等Double则使标志位为true;
flag=true;
//临时结果为空,以便从下个字母开始进行操作
result="";
}
}
//如果Double之后没有所对应的数字,则返回-1;
if(flag==true){
return "-1";
}
return finalResult;
}
}
写在最后:完整代码请访问:
https://gitee.com/kexianqun/interview
评论