X32专项练习部分17

顺序存储集合ArrayList

public class m19 {
    public static void main(String[] args) {
        List<Object> nums = new ArrayList<>();

        nums.add(0);
        nums.add(0);
        nums.add(4);
        nums.add(2);
        nums.add(5);
        nums.add(0);
        nums.add(3);
        nums.add(0);
        
        /*
        此时当前集合存在元素
        0 0 4 2 5 0 3 0
         */
        new m19().numQuest(nums);
        for (int i = 0; i < nums.size(); i++) {
            System.out.print(nums.get(i) + " ");
            // 0 4 2 5 3
        }
    }

    //precondition: nums.size() > 0
    //nums contains Integer objects
    public void numQuest(List nums) { // 0 0 4 2 5 0 3 0
        int k = 0;
        Integer zero = new Integer(0);
        while (k < nums.size()) {
            if (nums.get(k).equals(zero))
                nums.remove(k);
            k++;
        }
    }
    /*
    zero==0,如果get(k)==0,执行remove(k); ;
               size==8 ; k==0 , 因此第一次remove(0)
               删除索引为0的元素也就是第一个元素0
               然后k++, size()--;
    此时集合元素为 :[0,4,2,5,0,3,0]
               size==7; k==1,因此get(1)==4 !=0
               不执行remove();
               k++,因没有删除元素,size()不变
               
               此时可以发现
               集合元素如果执行remove方法删除一个元素后
               后面的索引自动向前补全
               
               也就是说
               当删除一个元素后
               后面的1个元素会忽略掉不检查是否为0
               这是ArrayList顺序存储的一大特性
               
               所以
               一旦涉及到删除指定所有元素
               建议使用迭代器
     */
}

for循环的执行顺序

class Print {
    static boolean out(char c) {
        System.out.println(c); // ABDC BDCB
        return true;
    }

    public static void main(String[] argv) {
        int i = 0;
        for (out('A'); out('B') && (i < 2); out('C')) {
            i++;
            out('D');
        }
        /*
        for循环的第1项只初始化1次
        然后在比较条件
        条件符合再进入循环体
        执行完循环体后再执行for循环的第3项
         */
    }
}

小根堆最大关键字存储的位置

	/*
    下标从1开始,在含有n个关键字的小根堆(堆顶元素最小)中
    关键字最大的记录有可能存储在()位置上
    正确答案: D

    [n/2]
    [n/2]-1
    1
    [n/2]+2

    就是小顶堆
    首先要明白:
    中括号取整,就是不大于这个数的最大整数
    第二要看清下标是从1开始的
    那么
                   1
               2       3
            4     5   6    7
            ...............n
    n不论是左子树还是右子树
    n的父结点一定是 [n/2]
    注意中括号的取整规则,正数就是下取整

    那么 [n/2] 这个结点还是有 子结点 的
    从 [n/2] + 1 开始一直到 n 都是叶子结点
    叶子结点就可能会是最大值,所以选D

    人家说的是可能
    只要具备可能性就行了

    堆是一个完全二叉树,最有可能在最后一个父节点的左子树的位置上
    因为数组从0开始计数
    最后一个父节点所在位置为n/2+1
    其左子树位置n/2+2
     */

哈希地址冲突及解决方案

	/*
    对于线性表(7,34,55,25,64,46,20,10)进行散列存储时
    若选用H(K)=K % 9作为散列函数,则计算的散列地址为1的元素有( )个。

    正确答案: D
    1   2   3   4
    4个
    分别是:55,64,46,10
    这4个数%9的余数都是1
    H(K)= K%9,表示除以9的余数
    由于地址重叠造成冲突,所以散列存储时,通常还要有解决冲突的办法

    比如线性探测再散列
    就是发生哈希地址冲突的时候
    顺序查看表中下一个单元
    知道找到一个空单元或查遍全表
     */

next数值序列

	/*
    已知串 S = "babab"
    其 Next 数值序列为
    正确答案: C

    01112
    01233
    01123
    01223

    其实算这种next值,不用那么麻烦,我看过很多种算法,有的复杂的我都不想看
    这里我把我的做法说一遍,相对简单点

    首先介绍2个概念,字符串的前缀和后缀
    这里的前缀是不包括最后一个字符的子串
    后缀是不包含第一个字符的子串
    拿题目中的字符串a="babab"举例

    首先第一位0,第二位1
    这个是固定的

    第三位,字符串是“bab”,这时候“bab”的前缀有b,ba
        后缀有ab,b

        可以看出前后缀 相等的 最长的 字符串只有b
        注意是找 相等的 最长的
        相等的是前提
        因为b的长度是1,所以这里第三位的next值就是1

    到了第四位,字符串是“baba”
        前缀是b,ba,bab
        后缀是aba,ba,a
        这里可以看出前后缀相等的最长的字符串是ba,长度是2,因此第四位的next值是2

    到了第五位,字符串是“babab”
        前缀是b,ba,bab,baba
        后缀是abab,bab,ab,b
        这里可以看出前后缀相等的最长的字符串是bab
        长度是3,因此第五位的next值是3

    因此综合起来next值就是0 1 1 2 3,也就是答案C
     */

线性探测法探测次数

/*
    哈希查找中k个关键字具有同一哈希值
    若用线性探测法将这k个关键字对应的记录存入哈希表中,至少要进行几次探测
    正确答案: C
    k
    k+1
    k(k+1)/2
    1+k(k+1)/2

    问的是“至少”
    那么就是没有出现哈希冲突的情况

    第一个:直接找到坑,入坑,1次;
    第二个:和第一个同hash,找到坑被第一个给占了,找下一个,入坑,2次;
    第三个:第一个被占了,第二个也被占了,找第三个,入坑,3次;
    ... ...
    第n个:n次;
    一共:(1+n)*n / 2 次
    开放地址法(除了随机探测)都是(1+n)*n/2次

    线性探测法就是挨个查找
    直到找到空位即可

    如果n个关键字具有相同的哈希值
    那么需要进行n^2次线性探测
    这是至多的情况
     */

程序设计题:反转链表

public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;

        while(cur!=null){
            /*
            程序运行到此处
            创建辅助节点currentNode
            目的在于便于移动cur指针
            然后cur点下一个节点指向pre
            形成了next指针反向相反方向的情况
            也就是next实际上就是链表中的prev指针
            */
            ListNode currentNode = cur.next;
            cur.next = pre;
            pre = cur;
            cur = currentNode ;
        }
        /*
        程序运行到此处
        cur指针指向null
        pre指针指向表尾元素
        而pre的next方法指向前一个节点
        通过辅助指针反转链表
        */
        return pre;
    }
}

总目录

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muskfans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值