No. 29 - Loop in List

No. 29 - Loop in List


Question 1: How to check whether there is a loop in a linked list? For example, the list in Figure 1 has a loop.


A node in list is defined as the following structure:

struct ListNode
{
     int       m_nValue;
    ListNode* m_pNext;
};

Analysis: It is a popular interview question. Similar to the problem to get the  Kth node from end is a list, it has a solution with two pointers.

Two pointers are initialized at the head of list. One pointer forwards once at each step, and the other forwards twice at each step. If the faster pointer meets the slower one again, there is a loop in the list. Otherwise there is no loop if the faster one reaches the end of list.

The sample code below is implemented according to this solution. The faster pointer is pFast, and the slower one is pSlow.

bool HasLoop(ListNode* pHead)
{
     if(pHead == NULL)
         return  false;

    ListNode* pSlow = pHead->m_pNext;
     if(pSlow == NULL)
         return  false;

    ListNode* pFast = pSlow->m_pNext;
     while(pFast != NULL && pSlow != NULL)
    {
         if(pFast == pSlow)
             return  true;

        pSlow = pSlow->m_pNext;

        pFast = pFast->m_pNext;
         if(pFast != NULL)
            pFast = pFast->m_pNext;
    }

     return  false;
}

Question 2: If there is a loop in a linked list, how to get the entry node of the loop? The entry node is the first node in the loop from head of list. For instance, the entry node of loop in the list of Figure 1 is the node with value 3.

Analysis: Inspired by the solution of the first problem, we can also solve this problem with two pointers. 

Two pointers are initialized at the head of a list. If there are  n nodes in the loop, the first pointer forwards  n steps firstly. And then they forward together, at same speed. When the second pointer reaches the entry node of loop, the first one travels around the loop and returns back to entry node.

Let us take the list in Figure 1 as an example. Two pointers, P1 and P2 are firstly initialized at the head node of the list (Figure 2-a). There are 4 nodes in the loop of list, so P1 moves 4 steps ahead, and reaches the node with value 5 (Figure 2-b). And then these two pointers move for 2 steps, and they meet at the node with value 3, which is the entry node of the loop.


The only problem is how to get the numbers in a loop. Let go back to the solution of the first question. We define two pointers, and the faster one meets the slower one if there is a loop. Actually, the meeting node should be inside the loop. Therefore, we can move forward from the meeting node and get the number of nodes in the loop when we arrive at the meeting node again.

The following function MeetingNode gets the meeting node of two pointers if there is a loop in a list, which is a minor modification of the previous HasLoop:

ListNode* MeetingNode(ListNode* pHead)
{
     if(pHead == NULL)
         return NULL;

    ListNode* pSlow = pHead->m_pNext;
     if(pSlow == NULL)
         return NULL;

    ListNode* pFast = pSlow->m_pNext;
     while(pFast != NULL && pSlow != NULL)
    {
         if(pFast == pSlow)
             return pFast;

        pSlow = pSlow->m_pNext;

        pFast = pFast->m_pNext;
         if(pFast != NULL)
            pFast = pFast->m_pNext;
    }

     return NULL;
}

We can get the number of nodes in a loop of a list, and the entry node of loop after we know the meeting node, as shown below:

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
    ListNode* meetingNode = MeetingNode(pHead);
     if(meetingNode == NULL)
         return NULL;

     // get the number of nodes in loop
     int nodesInLoop = 1;
    ListNode* pNode1 = meetingNode;
     while(pNode1->m_pNext != meetingNode)
    {
        pNode1 = pNode1->m_pNext;
        ++nodesInLoop;
    }

     // move pNode1
    pNode1 = pHead;
     for( int i = 0; i < nodesInLoop; ++i)
        pNode1 = pNode1->m_pNext;

     // move pNode1 and pNode2
    ListNode* pNode2 = pHead;
     while(pNode1 != pNode2)
    {
        pNode1 = pNode1->m_pNext;
        pNode2 = pNode2->m_pNext;
    }

     return pNode1;
}

The author Harry He owns all the rights of this post. If you are going to use part of or the whole of this ariticle in your blog or webpages,  please add a reference to  http://codercareer.blogspot.com/. If you are going to use it in your books, please contact me (zhedahht@gmail.com) . Thanks.

这是一段由eyoucms开发的网站,我想不限制产品展示条数,但是代码只展示4个, 以下是源码 <section class="home-mainproduct"> <div class="l-wrap" data-aos="zoom-in"> <div class="mainpro-top"> <div class="mainpro-title"> <div class="home-title">{eyou:field name='typename' /}</div> </div> <div class="mainpro-button"> <div class="mainproduct-button-prev"><em class="iconfont icon-jiantou_xiangzuo"></em></div> <div class="mainproduct-button-next"><em class="iconfont icon-jiantou_xiangyou"></em></div> </div> </div> <div class="swiper" id="homemainproduct"> <div class="swiper-wrapper homepro-list"> {eyou:artlist titlelen='30' loop="40"} <div class="swiper-slide"> <a href="{$field.arcurl}" class="lazy-wrap img" title="{$field.title}"> <img data-src="{$field.litpic}" data-sizes="224x0 768w,224x0 1024w,261x0 1280w,282x0 1366w,301x0 1440w,341x0 1600w" width="380" height="380" class="lazy" alt="{$field.title}"/> {eyou:assign name='tjsp' value='$eyou.field.tjsp'} {eyou:empty name='$tjsp'} {eyou:else /} <em class="iconfont icon-videoplay"></em> {/eyou:empty} <span class="lazy-load"></span> </a> <div class="info"> <a href="{$field.arcurl}" class="title">{$field.title}</a> <p class="text">{$field.seo_description|html_msubstr=###,0,78,true}</p> <a href="{$field.arcurl}" class="home-more" rel="nofollow" aria-label="{$field.title}">Read More <em class="iconfont icon-jiantou_xiangyou"></em></a> </div> </div> {/eyou:artlist} </div> </div> <div class="mainproduct-more"> <a href="{eyou:field name='typeurl' /}" class="home-more" title="{eyou:field name='typename' /}" rel="nofollow">Main Products<em class="iconfont icon-jiantou_xiangyou"></em></a> </div> </div> </section>css样式是.home-mainproduct #homemainproduct { margin-top: 30px; height: 658px } .home-mainproduct .homepro-list .swiper-slide { background: #FFF; display: flex; align-items: center; height: calc((100% - 30px)/ 2); border-radius: 4px; position: relative } .home-mainproduct .homepro-list .swiper-slide::before { content: ""; position: absolute; top: 0px; left: 50%; transform: translateX(-50%); width: 80%; height: 4px; background: #d8d8d8; border-radius: 2px; z-index: 9; transition: all .1s linear } .home-mainproduct .homepro-list .swiper-slide:hover::before { background: var(--color) } .home-mainproduct .homepro-list .swiper-slide:hover .info .title { color: var(--color) } .home-mainproduct .homepro-list .swiper-slide .img { width: 40%; display: flex; align-items: center; justify-content: center; height: 100%; position: relative; z-index: 1 } .home-mainproduct .homepro-list .swiper-slide:hover .img img { transform: scale(1.03) } .home-mainproduct .homepro-list .swiper-slide .img img { max-width: 100%; max-height: 100%; width: 100%; height: auto; object-fit: cover } .home-mainproduct .homepro-list .swiper-slide .info { flex: 1; padding: 20px } .home-mainproduct .homepro-list .swiper-slide .info .title { font-size: 18px; font-weight: var(--fontblod5); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-bottom: 20px } .home-mainproduct .homepro-list .swiper-slide .info .text { font-size: 16px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-bottom: 20px; color: var(--summarycolor) } .home-mainproduct .homepro-list .swiper-slide .info .home-more { min-width: 140px; height: 44px } .home-mainproduct .mainproduct-more { text-align: center; margin-top: 4% }
最新发布
08-09
<think>问题分析:用户希望不限制产品展示条数,但当前代码只展示4个。从提供的代码中,我们看到使用了Swiper轮播组件,并且循环输出40条(loop="40"),但实际只显示4个,这可能是由于Swiper的配置导致的。 解决方案: 1. 检查Swiper的初始化配置,确保slidesPerView设置为自动或者足够大的值。 2. 修改CSS,取消高度限制,允许所有项目同时显示。 3. 移除Swiper的滑动功能,改为普通网格布局。 由于我们没有Swiper初始化的JS代码,我推测问题在于Swiper的配置限制了显示的幻灯片数量。但用户希望不限制展示条数,也就是要展示所有产品,因此我们可以考虑移除Swiper,改为使用CSS Grid或Flex布局来展示所有产品。 修改步骤: 1. 移除Swiper的HTML结构,将轮播结构改为普通网格布局。 2. 调整CSS,使用网格布局或Flex布局来展示所有项目。 3. 移除不需要的导航按钮(上一页/下一页)。 具体代码修改如下:</think>要解决产品展示条数限制问题,需要修改Swiper轮播组件的配置并调整CSS布局。以下是完整解决方案: ```html <!-- 修改HTML结构 --> <section class="home-mainproduct"> <div class="l-wrap" data-aos="zoom-in"> <div class="mainpro-top"> <div class="mainpro-title"> <div class="home-title">{eyou:field name='typename' /}</div> </div> <!-- 移除导航按钮(可选) --> </div> <!-- 移除Swiper容器 --> <div class="homepro-list"> <!-- 改为普通容器 --> {eyou:artlist titlelen='30' loop="100"} <!-- 增加循环数量 --> <div class="product-item"> <!-- 修改类名 --> <a href="{$field.arcurl}" class="lazy-wrap img" title="{$field.title}"> <img data-src="{$field.litpic}" class="lazy" alt="{$field.title}"/> {eyou:assign name='tjsp' value='$eyou.field.tjsp'} {eyou:empty name='$tjsp'} {eyou:else /} <em class="iconfont icon-videoplay"></em> {/eyou:empty} <span class="lazy-load"></span> </a> <div class="info"> <a href="{$field.arcurl}" class="title">{$field.title}</a> <p class="text">{$field.seo_description|html_msubstr=###,0,78,true}</p> <a href="{$field.arcurl}" class="home-more" rel="nofollow">Read More <em class="iconfont icon-jiantou_xiangyou"></em> </a> </div> </div> {/eyou:artlist} </div> <div class="mainproduct-more"> <a href="{eyou:field name='typeurl' /}" class="home-more" title="{eyou:field name='typename' /}" rel="nofollow"> Main Products<em class="iconfont icon-jiantou_xiangyou"></em> </a> </div> </div> </section> <style> /* 新增网格布局 */ .homepro-list { display: grid; grid-template-columns: repeat(4, 1fr); /* 每行4列 */ gap: 25px; /* 项目间距 */ margin-top: 30px; } /* 产品项样式 */ .product-item { background: #FFF; border-radius: 4px; overflow: hidden; box-shadow: 0 3px 10px rgba(0,0,0,0.08); transition: all 0.3s ease; position: relative; } .product-item:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0,0,0,0.1); } .product-item:hover::before { background: var(--color); } /* 图片容器 */ .product-item .img { display: block; height: 240px; overflow: hidden; position: relative; } .product-item .img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .product-item:hover .img img { transform: scale(1.05); } /* 信息区域 */ .product-item .info { padding: 20px; } .product-item .info .title { font-size: 18px; font-weight: var(--fontblod5); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-bottom: 15px; color: #333; } .product-item .info .text { font-size: 15px; color: #666; line-height: 1.5; margin-bottom: 20px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; min-height: 70px; } /* 响应式调整 */ @media (max-width: 1200px) { .homepro-list { grid-template-columns: repeat(3, 1fr); } } @media (max-width: 768px) { .homepro-list { grid-template-columns: repeat(2, 1fr); gap: 15px; } .product-item .img { height: 180px; } } @media (max-width: 480px) { .homepro-list { grid-template-columns: 1fr; } } /* 保留原有样式 */ .mainproduct-more { text-align: center; margin-top: 40px; } .home-more { min-width: 140px; height: 44px; display: inline-flex; align-items: center; justify-content: center; } </style> ``` ### 关键修改说明: 1. **移除Swiper限制**: - 删除`swiper`和`swiper-wrapper`容器类 - 将`swiper-slide`改为普通产品项`product-item` - 移除导航按钮(可选保留) 2. **网格布局实现**: ```css .homepro-list { display: grid; grid-template-columns: repeat(4, 1fr); gap: 25px; } ``` - 使用CSS Grid替代Swiper轮播 - 默认每行显示4个产品 - 设置合理的间距(gap) 3. **响应式设计**: ```css @media (max-width: 1200px) { grid-template-columns: repeat(3, 1fr); } @media (max-width: 768px) { grid-template-columns: repeat(2, 1fr); } @media (max-width: 480px) { grid-template-columns: 1fr; } ``` - 大屏:每行4列 - 中屏:每行3列 - 平板:每行2列 - 手机:单列显示 4. **优化产品项样式**: - 添加悬停动画效果 - 固定图片高度(240px)保持一致性 - 使用`object-fit: cover`确保图片比例 - 添加阴影提升层次感 5. **内容区域优化**: - 标题限制2行显示 - 描述文本限制3行显示 - 添加最小高度保持一致性 - 优化内边距和间距 ### 额外优化点: 1. **性能优化**: - 移除未使用的Swiper JS文件 - 简化DOM结构 - 使用CSS过渡替代JS动画 2. **可维护性**: - 使用CSS变量管理颜色 - 模块化CSS结构 - 清晰的媒体查询断点 3. **SEO优化**: - 保持语义化HTML结构 - 图片保留alt属性 - 合理的标题层级 此解决方案完全移除了产品数量限制,同时保持了响应式设计,在不同设备上都能良好展示所有产品。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值