算法训练day02

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

解题思路:
//思路一:定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数
	public int MoreThanHalfNum_Solution(int [] array) {
    
    
        if (array == null || array.length == 0) return -1;
        int half = array.length / 2;
        HashMap<Integer,Integer> map = new HashMap<>();
        for (int i = 0; i < array.length; i++) {
    
    
            if (map.containsKey(array[i])) {
    
    
                int count = map.get(array[i]);
                count++;
                map.put(array[i],count);
            } else {
    
    
                map.put(array[i],1);
            }
            if (map.get(array[i]) > half) {
    
    
                return array[i];
            }
        }
        return -1;
	}
//思路二:排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求
	public int MoreThanHalfNum_Solution2(int [] array) {
    
    
        if (array == null || array.length == 0) return -1;
        Arrays.sort(array);
        int target = array[array.length/2];
        int count = 0;
        for (int i = 0; i < array.length; i++) {
    
    
            if (array[i] == target) {
    
    
                count++;
            }
            if (count > array.length/2) {
    
    
                return target;
            }
        }
        return -1;
    }
//思路三:目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,到最后剩下的一个数就是该数字。如果剩下两个,那么这两个也是一样的,就是结果),在其基础上把最后剩下的一个数字或者两个回到原来数组中,将数组遍历一遍统计一下数字出现次数进行最终判断。
	public int MoreThanHalfNum_Solution3(int [] array) {
    
    
        if (array == null || array.length == 0) return -1;
        int target = array[0];//第一个数
        int times = 1;//出现次数
        for (int i = 1; i < array.length; i++) {
    
    
            if (times == 0) {
    
    
                target = array[i];//重新开始
                times = 1;
            }
            else if (target == array[i]) {
    
    
                times++;
            }
            else {
    
    
                times--;
            }
        }
        //判断一下
        times = 0;
        for (int i = 0; i < array.length; i++) {
    
    
            if (target == array[i]) {
    
    
                times++;
            }
        }
        return times > array.length/2 ? target : -1;
    }

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

public  String replaceSpace(StringBuffer str) {
    
    
	return str.toString().replaceAll("\\s","%20");
}
//解题思路:
//虽然是替换问题,但是生成的字符串整体变长了,所以,一定涉及到字符串中字符的移动问题
//移动方向一定是向后移动,所以现在的问题无非是移动多少的问题
//因为是 ' ' -> "%20",是1换3,所以可以先统计原字符串中空格的个数(设为n),然后可以计算出新字符串的长度
//所以:new_length = old_length + 2*n
//最后,定义新老索引(或者指针),各自指向新老空间的结尾,然后进行old->new的移动
//如果是空格,就连续放入“%20”,其他平移即可。
import java.util.*;
public class Solution {
    
    
    public String replaceSpace(StringBuffer str) {
    
    
    	//统计字符串中空格的个数
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
    
    
            if (str.charAt(i) == ' ') {
    
    
                count++;
            }
        }

        int new_length = str.length() + 2*count; // 新字符串的长度
        int old_end = str.length() -1; //索引老字符串最后一个有效位置
        int new_end = new_length -1;//索引新字符串最后一个有效位置
        str.setLength(new_length); //把空间设置为想要的长度,防止越界
        while (old_end >= 0 && new_end >= 0) {
    
    
            if (str.charAt(old_end) == ' ') {
    
    
                //当前位置是空格   放%20 后移
                str.setCharAt(new_end--,'0');
                str.setCharAt(new_end--,'2');
                str.setCharAt(new_end--,'%');
                old_end--;
            } else {
    
    
                //不是空格,平移就可以
                str.setCharAt(new_end, str.charAt(old_end)); //把old_end的值放到new_end的位置上
                old_end--;
                new_end--;
            }
        }
        return str.toString();
    }
}

3.输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。
OJ链接

解题思路:
//这道题整体解决思路很多,可以使用stack,可以递归,也可以将数据保存数组,逆序数组
//思路一:stack 先进后出  出栈后放入数组中
public ArrayList<Integer> printListFromTailToHeadCore(ListNode listNode) {
    
    
        ArrayList<Integer> list = new ArrayList<>();
        if (listNode == null) {
    
    
            return list;
        }
        Stack<Integer> stack = new Stack<>();
        while (listNode != null) {
    
    
            stack.push(listNode.val);
            listNode = listNode.next;
        }
        while (!stack.empty()) {
    
    
            list.add(stack.pop());
        }
        return list;
    }

    

4.给定节点数为 n 二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。
OJ链接

///解题思路:
//根据root节点,将中序划分成 根左边,根右边 两部分中序子序列
//遍历中序找到前序根节点在中序中的位置
//root->left递归生成
//root->right递归生成
public class Solution {
    
    
    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
    
    
        if (pre == null || vin == null || pre.length != vin.length) {
    
    
            return null;
        }
        return reConstructBinaryTreeHelper(pre,vin,0,vin.length-1);

    }
    
    public int pi = 0;
    public  TreeNode reConstructBinaryTreeHelper(int[] pre,int[] vin,int begin,int end) {
    
    
        if (begin > end) {
    
    
            return null;
        }
        TreeNode root = new TreeNode(pre[pi]);
        int ri = findIndex(vin,begin,end,pre[pi]);
        pi++;
        root.left = reConstructBinaryTreeHelper(pre,vin,begin,ri-1);
        root.right = reConstructBinaryTreeHelper(pre,vin,ri+1,end);
        return root;
    }
     // 中序找到根节点
    public int findIndex(int[] vin,int begin, int end,int key) {
    
    
        for (int i = 0; i <= end; i++) {
    
    
            if (vin[i] == key) {
    
    
                return i;
            }
        }
        return -1;
    }
}

Guess you like

Origin blog.csdn.net/ccyzq/article/details/121461114